{"views":[{"name":"admin_action_logs","schema":"public","definition":" SELECT id,\n    user_id AS admin_user_id,\n    event_action AS action_type,\n        CASE\n            WHEN resource_type = 'user'::text AND resource_id ~ '^[0-9a-f-]{36}$'::text THEN resource_id::uuid\n            ELSE NULL::uuid\n        END AS target_user_id,\n    tenant_id AS target_tenant_id,\n    metadata,\n    ip_address,\n    user_agent,\n    \"timestamp\",\n    created_at\n   FROM comprehensive_audit_logs\n  WHERE event_category = 'admin'::text;"},{"name":"audit_logs","schema":"public","definition":" SELECT id,\n    \"timestamp\",\n    user_id,\n    tenant_id,\n    event_action AS action,\n    COALESCE(resource_type, 'unknown'::text) AS resource_type,\n    resource_id,\n    old_value,\n    new_value,\n    ip_address,\n    user_agent,\n    session_id,\n    metadata,\n    severity,\n    created_at\n   FROM comprehensive_audit_logs;"},{"name":"business_attention_feed","schema":"public","definition":" SELECT a.id,\n    a.tenant_id,\n    a.opportunity_id,\n    a.kind,\n    a.priority,\n    a.state,\n    a.title,\n    a.summary,\n    a.due_at,\n    a.due_at IS NOT NULL AND a.due_at < now() AS is_overdue,\n    a.action_route,\n    a.source_state,\n    a.acknowledged_at,\n    a.created_at,\n    a.updated_at,\n    o.contact_id,\n    o.category,\n    o.lifecycle_state,\n    o.proposal_state,\n    o.payment_state,\n    o.fulfillment_state,\n    o.estimated_value,\n    o.quoted_amount,\n    o.balance_amount\n   FROM business_attention_items a\n     JOIN business_opportunities o ON o.id = a.opportunity_id AND o.tenant_id = a.tenant_id\n  WHERE a.state = ANY (ARRAY['open'::text, 'acknowledged'::text]);"},{"name":"contacts_with_tenants","schema":"public","definition":" SELECT uc.id,\n    uc.name,\n    uc.first_name,\n    uc.last_name,\n    uc.phone,\n    uc.email,\n    uc.second_email,\n    uc.address,\n    uc.address2,\n    uc.address3,\n    uc.address4,\n    uc.city,\n    uc.state,\n    uc.zip,\n    uc.lat,\n    uc.lng,\n    uc.geocoded_at,\n    uc.carrier,\n    uc.carrier_name,\n    uc.policy_number,\n    uc.policy_number2,\n    uc.policy_number3,\n    uc.policy_number4,\n    uc.claim_number,\n    uc.claim_number2,\n    uc.claim_number3,\n    uc.claim_number4,\n    uc.dol,\n    uc.claim_notes,\n    uc.adjuster_name,\n    uc.adjuster_phone,\n    uc.adjuster_email,\n    uc.assigned_estimator,\n    uc.estimator_phone,\n    uc.roof_type,\n    uc.roof_age,\n    uc.property_data,\n    uc.property_square_feet,\n    uc.property_parcel_id,\n    uc.property_data_fetched_at,\n    uc.property_owner_name,\n    uc.property_assessed_value,\n    uc.property_bedrooms,\n    uc.property_bathrooms,\n    uc.property_year_built,\n    uc.property_lot_size,\n    uc.property_data_jurisdiction,\n    uc.property_data_source,\n    uc.property_zoning,\n    uc.property_land_use,\n    uc.property_market_value,\n    uc.property_tax_amount,\n    uc.property_last_sale_date,\n    uc.property_last_sale_price,\n    uc.normalized_phone,\n    uc.normalized_email,\n    uc.normalized_address,\n    uc.permit_data,\n    uc.permit_scanned_at,\n    uc.has_recent_roof_permit,\n    uc.roof_permit_finaled_date,\n    uc.raw_data,\n    uc.link_group_id,\n    ctm.tenant_id::text AS tenant_org_id,\n    ctm.assigned_to,\n    ctm.assigned_rep,\n    ctm.assigned_user,\n    ctm.status,\n    ctm.contact_status,\n    ctm.service_status,\n    ctm.lead_stage,\n    ctm.jobs_stage,\n    ctm.claim_stage,\n    ctm.graduated_at,\n    ctm.appt_date,\n    ctm.appt_time,\n    ctm.notes,\n    ctm.notes2,\n    ctm.notes3,\n    ctm.notes4,\n    ctm.additional_notes,\n    ctm.source,\n    ctm.priority,\n    ctm.quality_score,\n    ctm.lead_score,\n    ctm.lead_tags,\n    ctm.claim_status,\n    ctm.insurance_claim_status,\n    ctm.estimate_status,\n    ctm.job_value,\n    ctm.work_classification,\n    ctm.salesperson_number,\n    ctm.contact_role,\n    ctm.lead_id,\n    ctm.contact_ref,\n    ctm.last_touched_at,\n    ctm.last_contact,\n    ctm.deleted_at,\n    ctm.deleted_by,\n    ctm.deletion_reason,\n    ctm.created_at AS membership_created_at,\n    ctm.updated_at AS membership_updated_at\n   FROM unified_contacts uc\n     JOIN contact_tenant_memberships ctm ON ctm.contact_id = uc.id;"},{"name":"dnc_compliance_summary","schema":"public","definition":" SELECT (( SELECT count(*) AS count\n           FROM lead_deck\n          WHERE lead_deck.phone IS NOT NULL AND lead_deck.phone <> ''::text)) + (( SELECT count(*) AS count\n           FROM unified_contacts\n          WHERE unified_contacts.phone IS NOT NULL AND unified_contacts.phone <> ''::text)) AS total_leads_with_phone,\n    (( SELECT count(*) AS count\n           FROM lead_deck\n          WHERE lead_deck.dnc_checked_at >= (now() - '31 days'::interval))) + (( SELECT count(*) AS count\n           FROM unified_contacts\n          WHERE unified_contacts.dnc_checked_at >= (now() - '31 days'::interval))) AS leads_scanned_recently,\n    ( SELECT count(*) AS count\n           FROM dnc_leads_due_for_rescan) AS leads_due_for_rescan,\n    (( SELECT count(*) AS count\n           FROM lead_deck\n          WHERE lead_deck.is_dnc = true)) + (( SELECT count(*) AS count\n           FROM unified_contacts\n          WHERE unified_contacts.is_dnc = true)) AS total_dnc_quarantined,\n    ( SELECT max(dnc_audit_runs.completed_at) AS max\n           FROM dnc_audit_runs\n          WHERE dnc_audit_runs.status = 'completed'::text) AS last_successful_scan,\n    ( SELECT min(dnc_audit_runs.started_at) AS min\n           FROM dnc_audit_runs\n          WHERE dnc_audit_runs.status = 'running'::text) AS oldest_running_scan;"},{"name":"dnc_leads_due_for_rescan","schema":"public","definition":" SELECT ld.id AS lead_id,\n    'lead_deck'::text AS lead_table,\n    ld.phone,\n    ld.dnc_checked_at,\n    ld.is_dnc,\n    ld.tenant_org_id,\n    EXTRACT(epoch FROM now() - COALESCE(ld.dnc_checked_at, ld.created_at)) / 86400::numeric AS days_since_check\n   FROM lead_deck ld\n  WHERE ld.phone IS NOT NULL AND ld.phone <> ''::text AND (ld.dnc_checked_at IS NULL OR ld.dnc_checked_at < (now() - '31 days'::interval))\nUNION ALL\n SELECT uc.id AS lead_id,\n    'unified_contacts'::text AS lead_table,\n    uc.phone,\n    uc.dnc_checked_at,\n    uc.is_dnc,\n    uc.tenant_org_id,\n    EXTRACT(epoch FROM now() - COALESCE(uc.dnc_checked_at, uc.created_at)) / 86400::numeric AS days_since_check\n   FROM unified_contacts uc\n  WHERE uc.phone IS NOT NULL AND uc.phone <> ''::text AND (uc.dnc_checked_at IS NULL OR uc.dnc_checked_at < (now() - '31 days'::interval));"},{"name":"entitlements_view","schema":"public","definition":" SELECT ts.tenant_id,\n    ts.plan_id,\n    p.slug AS plan_slug,\n    p.name AS plan_name,\n    p.tier AS plan_tier,\n    ts.status AS subscription_status,\n    ts.trial_ends_at,\n    ts.seat_count,\n    p.included_seats,\n    ts.billing_cycle,\n    pf.feature_key,\n    pf.limit_value,\n    pf.is_boolean\n   FROM tenant_subscriptions ts\n     JOIN plans p ON p.id = ts.plan_id\n     LEFT JOIN plan_features pf ON pf.plan_id = p.id;"},{"name":"incoming_users","schema":"public","definition":" SELECT ui.id,\n    ui.email,\n    ui.name,\n    ui.tenant_id,\n    ui.role,\n    ui.status,\n    ui.created_at,\n    ui.expires_at,\n    'invitation'::text AS source,\n    ui.invited_by AS source_user_id\n   FROM user_invitations ui\n  WHERE ui.status = 'pending'::text\nUNION ALL\n SELECT ps.id,\n    ps.email,\n    ps.full_name AS name,\n    NULL::uuid AS tenant_id,\n    ps.role,\n    ps.status,\n    ps.created_at,\n    ps.expires_at,\n    'self_signup'::text AS source,\n    ps.created_by AS source_user_id\n   FROM pending_signups ps\n  WHERE ps.status = ANY (ARRAY['pending'::text, 'pending_agreement'::text, 'pending_approval'::text]);"},{"name":"jobs_crew_view","schema":"public","definition":" SELECT id,\n    tenant_id,\n    job_number,\n    job_type,\n    priority,\n    status,\n    assigned_crew_id,\n    assigned_pm_id,\n    scheduled_date,\n    scheduled_time,\n    appointment_date,\n    started_at,\n    completed_at,\n    property_address,\n    city,\n    state,\n    zip,\n    latitude,\n    longitude,\n    split_part(COALESCE(customer_name, ''::text), ' '::text, 1) AS customer_first_name,\n    special_instructions,\n    crew_notes,\n    work_auth_signed,\n    tarp_installed,\n    photos_uploaded,\n    docs_complete,\n    created_at,\n    updated_at\n   FROM jobs j\n  WHERE (EXISTS ( SELECT 1\n           FROM user_tenant_memberships m\n          WHERE m.user_id = uid() AND m.tenant_id = j.tenant_id AND m.status = 'active'::text)) AND (is_manager_or_higher_strict(uid(), tenant_id) OR has_acting_pm_grant(uid(), tenant_id) OR assigned_pm_id = uid() OR assigned_crew_id = uid());"},{"name":"jobs_package_readiness","schema":"public","definition":" SELECT id AS job_id,\n    tenant_id,\n    job_number,\n    status AS job_status,\n    verified_at,\n    contact_claim_id,\n    work_auth_signed,\n    photos_uploaded,\n    docs_complete,\n    verified_at IS NOT NULL AS pm_verified,\n    tarping_invoice_id IS NOT NULL AS invoice_present,\n    COALESCE(carrier_name, ''::text) <> ''::text AS carrier_present,\n    COALESCE(policy_number, ''::text) <> ''::text AS policy_present,\n    COALESCE(claim_number, ''::text) <> ''::text AS claim_present,\n    COALESCE(property_address, ''::text) <> ''::text AND COALESCE(customer_name, ''::text) <> ''::text AS contact_present,\n    work_auth_signed AND photos_uploaded AND docs_complete AND verified_at IS NOT NULL AND tarping_invoice_id IS NOT NULL AND COALESCE(carrier_name, ''::text) <> ''::text AND COALESCE(policy_number, ''::text) <> ''::text AND COALESCE(claim_number, ''::text) <> ''::text AS package_ready\n   FROM jobs j;"},{"name":"lead_deck_compat","schema":"public","definition":" SELECT id,\n    lead_id,\n    name,\n    phone,\n    email,\n    address,\n    city,\n    state,\n    zip,\n    status,\n    priority,\n    source,\n    assigned_to,\n    tenant_org_id,\n    notes,\n    created_at,\n    updated_at,\n    deleted_at,\n    deleted_by,\n    deletion_reason,\n    property_data,\n    property_square_feet,\n    property_parcel_id,\n    property_data_fetched_at,\n    property_owner_name,\n    property_assessed_value,\n    property_bedrooms,\n    property_bathrooms,\n    property_year_built,\n    property_lot_size,\n    COALESCE(property_data ->> 'property_data_jurisdiction'::text, NULL::text)::character varying AS property_data_jurisdiction,\n    lead_stage,\n    graduated_at,\n    lat,\n    lng,\n    geocoded_at,\n    geocode_confidence,\n    archived_at,\n    lost_at,\n    dnc_at\n   FROM unified_contacts\n  WHERE graduated_at IS NULL AND assigned_to IS NULL AND deleted_at IS NULL;"},{"name":"lead_timeline","schema":"public","definition":" SELECT 'call:'::text || cl.id AS event_id,\n    cl.tenant_id AS tenant_org_id,\n    COALESCE(cl.contact_id::text, cl.lead_id) AS lead_id,\n    'call'::text AS kind,\n    cl.outcome::text AS subkind,\n    cl.created_at AS occurred_at,\n    cl.user_id AS actor_user_id,\n    COALESCE(NULLIF(cl.notes, ''::text), 'Call '::text || COALESCE(cl.outcome::text, 'logged'::text)) AS title,\n    cl.transcript AS body,\n    jsonb_build_object('direction', cl.direction, 'duration_seconds', cl.duration_seconds, 'recording_url', cl.recording_url, 'twilio_status', cl.twilio_status, 'phone', cl.phone_called) AS metadata\n   FROM call_logs cl\nUNION ALL\n SELECT 'sms:'::text || sh.id AS event_id,\n    sh.tenant_id AS tenant_org_id,\n    sh.contact_id::text AS lead_id,\n    'sms'::text AS kind,\n    sh.direction AS subkind,\n    sh.created_at AS occurred_at,\n    sh.user_id AS actor_user_id,\n        CASE\n            WHEN sh.direction = 'outbound'::text THEN 'SMS sent'::text\n            ELSE 'SMS received'::text\n        END AS title,\n    sh.body,\n    jsonb_build_object('from', sh.from_number, 'to', sh.to_number, 'status', sh.status, 'twilio_sid', sh.twilio_sid) AS metadata\n   FROM sms_history sh\nUNION ALL\n SELECT 'lane:'::text || la.id AS event_id,\n    la.tenant_org_id,\n    la.lead_id::text AS lead_id,\n    'lane'::text AS kind,\n    la.to_state::text AS subkind,\n    la.created_at AS occurred_at,\n    la.actor_user_id,\n    'Lane → '::text || la.to_state::text AS title,\n    COALESCE(la.notes, la.disclosure_text) AS body,\n    jsonb_build_object('from_state', la.from_state, 'to_state', la.to_state, 'disclosure', la.disclosure_text) AS metadata\n   FROM lead_lane_audit la\nUNION ALL\n SELECT 'compliance:'::text || ce.id AS event_id,\n        CASE\n            WHEN ce.tenant_org_id ~* '^[0-9a-f-]{36}$'::text THEN ce.tenant_org_id::uuid\n            ELSE NULL::uuid\n        END AS tenant_org_id,\n    ce.lead_id,\n    'compliance'::text AS kind,\n    ce.check_type AS subkind,\n    ce.checked_at AS occurred_at,\n    ce.checked_by AS actor_user_id,\n    (ce.check_type || ' → '::text) || COALESCE(ce.decision, ce.result, 'logged'::text) AS title,\n    ce.reason AS body,\n    jsonb_build_object('provider', ce.provider, 'result', ce.result, 'decision', ce.decision, 'phone', ce.phone_number) AS metadata\n   FROM communication_compliance_events ce\nUNION ALL\n SELECT 'note:'::text || cn.id AS event_id,\n    cn.tenant_org_id,\n    cn.contact_id::text AS lead_id,\n    'note'::text AS kind,\n    COALESCE(cn.note_type, 'note'::text) AS subkind,\n    cn.created_at AS occurred_at,\n    cn.user_id AS actor_user_id,\n    COALESCE(cn.user_name, cn.user_email, 'Note'::text) AS title,\n    cn.content AS body,\n    jsonb_build_object('claim_id', cn.claim_id) AS metadata\n   FROM contact_notes cn\nUNION ALL\n SELECT 'activity:'::text || al.id AS event_id,\n        CASE\n            WHEN al.tenant_id ~* '^[0-9a-f-]{36}$'::text THEN al.tenant_id::uuid\n            ELSE NULL::uuid\n        END AS tenant_org_id,\n    al.contact_id AS lead_id,\n    'activity'::text AS kind,\n    al.activity_type AS subkind,\n    al.created_at AS occurred_at,\n    al.user_id AS actor_user_id,\n    al.title,\n    al.description AS body,\n    al.metadata\n   FROM activity_log al;"},{"name":"profiles_safe","schema":"public","definition":" SELECT id,\n    email,\n    name,\n    phone,\n    role,\n    active,\n    company,\n    tenant_org_id,\n    last_login,\n    last_login_at,\n    created_at,\n    updated_at,\n    user_drive_folder_id,\n    drive_provisioned_at,\n    drive_provisioning_status,\n    leaddeck_sheet_id,\n    license_number,\n    tcpa_certified_at\n   FROM profiles;"},{"name":"qr_code_analytics","schema":"public","definition":" SELECT qc.id AS qr_id,\n    qc.tenant_id,\n    qc.campaign_id,\n    qc.short_code,\n    qc.title,\n    qc.type,\n    qc.active,\n    qc.destination_mode,\n    qc.destination_value,\n    count(qe.id) FILTER (WHERE qe.event_type = 'scan'::text) AS scans,\n    count(qe.id) FILTER (WHERE qe.event_type = 'redirect'::text) AS redirects,\n    count(qe.id) FILTER (WHERE qe.event_type = 'conversion'::text) AS conversions,\n    max(qe.created_at) AS last_event_at,\n    qc.created_at\n   FROM qr_codes qc\n     LEFT JOIN qr_events qe ON qe.qr_id = qc.id\n  GROUP BY qc.id;"},{"name":"security_active_user_tenant_memberships","schema":"public","definition":" SELECT id,\n    user_id,\n    tenant_id,\n    status,\n    invited_by,\n    joined_at,\n    last_accessed_at,\n    is_owner\n   FROM user_tenant_memberships\n  WHERE status = 'active'::text;"},{"name":"tenant_organizations","schema":"public","definition":" SELECT id,\n    name AS company_name,\n    name,\n    tenant_type,\n    owner_id,\n    status,\n    created_at,\n    updated_at,\n    settings,\n    company_slug,\n    company_legal_name,\n    company_dba_name,\n    company_address,\n    company_city,\n    company_state,\n    company_zip,\n    company_phone,\n    company_email,\n    company_logo_url AS logo_url,\n    company_logo_url,\n    letterhead_config,\n    is_active,\n    company_descriptor,\n    customer_facing_title,\n    branded_sender_email,\n    company_website,\n    company_mailing_address\n   FROM tenants;"},{"name":"user_tenant_access","schema":"public","definition":" SELECT COALESCE(r.user_id, m.user_id) AS user_id,\n    COALESCE(r.tenant_id, m.tenant_id) AS tenant_id,\n    r.role::text AS role,\n    COALESCE(m.is_owner, false) AS is_owner,\n    COALESCE(m.status, 'active'::text) AS membership_status,\n    r.role IS NOT NULL AS has_role,\n    m.user_id IS NOT NULL AS has_membership,\n    COALESCE(r.role::text,\n        CASE\n            WHEN m.is_owner THEN 'Tenant Owner'::text\n            ELSE 'Rep'::text\n        END) AS effective_role,\n    COALESCE(r.assigned_at, m.joined_at) AS granted_at\n   FROM user_roles r\n     FULL JOIN user_tenant_memberships m ON r.user_id = m.user_id AND r.tenant_id = m.tenant_id\n  WHERE COALESCE(r.user_id, m.user_id) = (( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin) OR (( SELECT role() AS role)) = 'service_role'::text;"},{"name":"v_active_tenant_users","schema":"public","definition":" SELECT p.id AS user_id,\n    p.email AS user_email,\n    p.name AS user_name,\n    p.phone AS user_phone,\n    p.active AS profile_active,\n    m.tenant_id,\n    m.status AS membership_status,\n    m.is_owner,\n    m.joined_at,\n    m.last_accessed_at\n   FROM profiles p\n     JOIN user_tenant_memberships m ON m.user_id = p.id\n  WHERE COALESCE(p.active, true) = true AND COALESCE(m.status, 'active'::text) = 'active'::text;"},{"name":"v_cached_parcel_roof_age_intel","schema":"public","definition":" SELECT id,\n    parcel_id,\n    lat,\n    lng,\n    year_built,\n    year_built_source,\n    roof_age_score,\n    roof_permit_year,\n    permit_count,\n    permit_source,\n    sqft_heated,\n    land_use,\n    zip,\n    notes,\n    viewport_key,\n    fetched_at,\n    created_at,\n    owner_name,\n    address,\n    assessed_value,\n    sale_price,\n    sale_date,\n    parcel_geometry,\n    geometry_source,\n    geometry_fetched_at\n   FROM cached_parcel_roof_ages;"},{"name":"v_canonical_stages","schema":"public","definition":" SELECT id,\n    tenant_org_id,\n    tenant_type,\n    tenancy_type,\n    pipeline_kind,\n    name,\n    order_index,\n    color,\n    is_active,\n    is_closed,\n    is_won,\n    is_template,\n    template_stage_key,\n    is_using_master_template,\n    derived_from_template_id,\n    adopted_admin_version,\n    created_at,\n    updated_at,\n    'pipeline_stages'::text AS source\n   FROM pipeline_stages ps\n  WHERE is_active = true;"},{"name":"v_command_center_events_safe","schema":"public","definition":" SELECT id,\n    tenant_id,\n    event_type,\n    priority,\n    status,\n    source_module,\n    created_by_role,\n    actor_display_name,\n    title,\n    cc_scrub_text(message) AS message,\n    requires_response,\n    requires_approval,\n    approval_status,\n    related_lead_id,\n    related_job_id,\n    related_claim_id,\n    created_at,\n    updated_at,\n    resolved_at\n   FROM command_center_events;"},{"name":"v_lead_intelligence_with_contact","schema":"public","definition":" SELECT s.id AS score_row_id,\n    s.tenant_org_id,\n    s.score_type,\n    s.subject_id,\n    s.score,\n    s.bucket,\n    s.label,\n    s.confidence,\n    s.reasons,\n    s.factors,\n    s.recommended_action,\n    s.stale,\n    s.dismissed,\n    s.last_calculated_at,\n    c.id AS contact_id,\n    c.name,\n    c.address,\n    c.city,\n    c.state,\n    c.zip,\n    c.phone,\n    c.lat,\n    c.lng,\n    c.assigned_to,\n    c.contact_status,\n    c.lead_stage,\n    c.graduated_at,\n    c.is_dnc,\n    c.carrier,\n    c.lead_score\n   FROM lead_intelligence_scores s\n     JOIN unified_contacts c ON c.id = s.subject_id AND c.deleted_at IS NULL\n  WHERE s.subject_type = 'contact'::text;"},{"name":"v_live_tenant_calls","schema":"public","definition":" SELECT acs.id AS session_id,\n    acs.tenant_org_id,\n    acs.rep_id,\n    acs.lead_id,\n    acs.phone_number,\n    acs.parent_call_sid,\n    acs.rep_call_sid,\n    acs.homeowner_call_sid,\n    acs.status,\n    acs.started_at,\n    acs.metadata,\n    ap.status AS rep_status,\n    p.name AS rep_name,\n    p.email AS rep_email\n   FROM active_call_sessions acs\n     LEFT JOIN agent_presence ap ON ap.user_id = acs.rep_id\n     LEFT JOIN profiles p ON p.id = acs.rep_id\n  WHERE acs.status <> ALL (ARRAY['ended'::text, 'failed'::text]);"},{"name":"v_ops_rollup_events_safe","schema":"public","definition":" SELECT id,\n    tenant_id,\n    event_type,\n    priority,\n    status,\n    source_module,\n    created_by_role,\n    actor_display_name,\n    title,\n    message,\n    requires_response,\n    requires_approval,\n    approval_status,\n    related_lead_id,\n    related_job_id,\n    related_claim_id,\n    created_at,\n    updated_at,\n    resolved_at\n   FROM v_command_center_events_safe\n  WHERE event_type = 'ops_anomaly_rollup'::text AND created_by_role = 'system:scetarping_ops_sentinel_rollup'::text;"},{"name":"v_ops_sentinel_events_safe","schema":"public","definition":" SELECT id,\n    tenant_id,\n    event_type,\n    priority,\n    status,\n    source_module,\n    created_by_role,\n    actor_display_name,\n    title,\n    message,\n    requires_response,\n    requires_approval,\n    approval_status,\n    related_lead_id,\n    related_job_id,\n    related_claim_id,\n    created_at,\n    updated_at,\n    resolved_at\n   FROM v_command_center_events_safe\n  WHERE event_type = 'ops_anomaly'::text AND created_by_role = 'system:scetarping_ops_sentinel'::text;"},{"name":"v_pa_settlement_kpis","schema":"public","definition":" SELECT tenant_org_id,\n    count(*) FILTER (WHERE (claim_status <> ALL (ARRAY['Settled'::text, 'Paid'::text, 'Closed'::text, 'Denied'::text, 'Withdrawn'::text])) OR claim_status IS NULL) AS open_cases,\n    count(*) FILTER (WHERE claim_status = 'Negotiating'::text) AS negotiating_cases,\n    count(*) FILTER (WHERE claim_status = 'Settled'::text) AS settled_cases,\n    count(*) FILTER (WHERE claim_status = ANY (ARRAY['Paid'::text, 'Closed'::text])) AS paid_closed_cases,\n    COALESCE(sum(pa_demand_amount) FILTER (WHERE claim_status <> ALL (ARRAY['Paid'::text, 'Closed'::text, 'Denied'::text, 'Withdrawn'::text])), 0::numeric) AS open_demand_total,\n    COALESCE(sum(carrier_offer_amount), 0::numeric) AS total_carrier_offers,\n    COALESCE(sum(settlement_amount), 0::numeric) AS total_settlement,\n    COALESCE(sum(expected_fee_amount), 0::numeric) AS total_expected_fees,\n    COALESCE(sum(fee_amount) FILTER (WHERE fee_status = 'Paid'::text), 0::numeric) AS total_collected_fees,\n    round(avg(settlement_amount) FILTER (WHERE settlement_amount IS NOT NULL), 2) AS avg_settlement,\n    round(avg((settlement_date - claim_filed_date)::numeric) FILTER (WHERE settlement_date IS NOT NULL AND claim_filed_date IS NOT NULL), 1) AS avg_days_to_settlement,\n    count(*) FILTER (WHERE claim_filed_date IS NOT NULL AND settlement_date IS NULL AND claim_filed_date <= (CURRENT_DATE - '30 days'::interval) AND claim_filed_date > (CURRENT_DATE - '60 days'::interval)) AS aging_30_60,\n    count(*) FILTER (WHERE claim_filed_date IS NOT NULL AND settlement_date IS NULL AND claim_filed_date <= (CURRENT_DATE - '60 days'::interval) AND claim_filed_date > (CURRENT_DATE - '90 days'::interval)) AS aging_60_90,\n    count(*) FILTER (WHERE claim_filed_date IS NOT NULL AND settlement_date IS NULL AND claim_filed_date <= (CURRENT_DATE - '90 days'::interval)) AS aging_over_90\n   FROM contact_claims cc\n  GROUP BY tenant_org_id;"},{"name":"v_priority_queue","schema":"public","definition":" SELECT lis.id AS score_id,\n    lis.tenant_org_id,\n    lis.score_type,\n    lis.subject_type,\n    lis.subject_id,\n    lis.score,\n    lis.label,\n    lis.bucket,\n    lis.confidence,\n    lis.rank,\n    lis.reasons,\n    lis.factors,\n    lis.recommended_action,\n    lis.recommended_method,\n    lis.recommended_script,\n    lis.dismissed,\n    lis.manually_boosted,\n    lis.manual_priority_override,\n    lis.stale,\n    lis.last_calculated_at,\n    lis.model_version,\n    uc.id AS contact_id,\n    uc.first_name,\n    uc.last_name,\n    COALESCE((uc.first_name || ' '::text) || uc.last_name, uc.first_name, uc.last_name) AS contact_name,\n    uc.address,\n    uc.city,\n    uc.state,\n    uc.zip,\n    uc.phone,\n    uc.email,\n    uc.assigned_to,\n    uc.status AS contact_status,\n    uc.lead_stage,\n    uc.jobs_stage,\n    uc.claim_stage,\n    uc.last_touched_at,\n    uc.roof_age,\n    uc.roof_permit_finaled_date,\n    uc.has_recent_roof_permit,\n    uc.property_year_built,\n    uc.property_assessed_value\n   FROM lead_intelligence_scores lis\n     LEFT JOIN unified_contacts uc ON (lis.subject_type = ANY (ARRAY['contact'::text, 'lead'::text, 'client'::text])) AND lis.subject_id = uc.id;"},{"name":"v_user_call_readiness","schema":"public","definition":" SELECT p.id AS user_id,\n    p.tenant_org_id::uuid AS tenant_id,\n    au.email,\n    p.name,\n    p.active,\n    p.phone AS profile_phone,\n    vc.phone_number AS verified_caller_id_number,\n    vc.forward_to_phone,\n    vc.verified_at,\n    ( SELECT tpn.phone_number\n           FROM tenant_phone_numbers tpn\n          WHERE tpn.tenant_org_id = p.tenant_org_id::uuid AND regexp_replace(tpn.phone_number, '\\D'::text, ''::text, 'g'::text) = regexp_replace(COALESCE(vc.phone_number, ''::text), '\\D'::text, ''::text, 'g'::text)\n         LIMIT 1) AS assigned_tenant_did,\n        CASE\n            WHEN p.phone IS NULL OR p.phone = ''::text THEN 'MissingProfilePhone'::text\n            WHEN vc.user_id IS NULL THEN 'MissingVerifiedCallerId'::text\n            WHEN vc.forward_to_phone IS NULL OR vc.forward_to_phone = ''::text THEN 'MissingForwarding'::text\n            WHEN vc.verified_at IS NULL THEN 'SetupIncomplete'::text\n            WHEN regexp_replace(p.phone, '\\D'::text, ''::text, 'g'::text) <> regexp_replace(vc.forward_to_phone, '\\D'::text, ''::text, 'g'::text) THEN 'ProfileHubMismatch'::text\n            ELSE 'Ready'::text\n        END AS readiness_status\n   FROM profiles p\n     JOIN users au ON au.id = p.id\n     LEFT JOIN LATERAL ( SELECT r.id,\n            r.user_id,\n            r.tenant_org_id,\n            r.phone_number,\n            r.friendly_name,\n            r.twilio_validation_sid,\n            r.twilio_caller_sid,\n            r.status,\n            r.is_default,\n            r.verified_at,\n            r.created_at,\n            r.updated_at,\n            r.forward_to_phone,\n            r.voice_url,\n            r.sms_url,\n            r.status_callback_url,\n            r.voice_recording_enabled,\n            r.voicemail_enabled,\n            r.voicemail_greeting,\n            r.forward_sms_enabled\n           FROM rep_verified_caller_ids r\n          WHERE r.user_id = p.id\n          ORDER BY r.verified_at DESC NULLS LAST\n         LIMIT 1) vc ON true\n  WHERE p.tenant_org_id IS NOT NULL;"},{"name":"v_voicemail_automation_health","schema":"public","definition":" SELECT tenant_org_id,\n    date_trunc('day'::text, started_at) AS day,\n    count(*) FILTER (WHERE voicemail_armed_template_id IS NOT NULL) AS armed,\n    count(*) FILTER (WHERE terminal_outcome = 'voicemail_left_auto'::text) AS auto_dropped,\n    count(*) FILTER (WHERE voicemail_armed_template_id IS NOT NULL AND terminal_outcome IS DISTINCT FROM 'voicemail_left_auto'::text) AS missed,\n        CASE\n            WHEN count(*) FILTER (WHERE voicemail_armed_template_id IS NOT NULL) = 0 THEN NULL::numeric\n            ELSE round(100.0 * count(*) FILTER (WHERE terminal_outcome = 'voicemail_left_auto'::text)::numeric / NULLIF(count(*) FILTER (WHERE voicemail_armed_template_id IS NOT NULL), 0)::numeric, 1)\n        END AS auto_drop_pct\n   FROM active_call_sessions acs\n  WHERE started_at >= (now() - '30 days'::interval)\n  GROUP BY tenant_org_id, (date_trunc('day'::text, started_at));"}],"format":"knocklaunch-database-catalog-v1","tables":[{"table":"audit_log_entries","schema":"auth","columns":[{"name":"instance_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"payload","type":"json","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"character varying(64)","default":"''::character varying","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"audit_log_entries_pkey","definition":"CREATE UNIQUE INDEX audit_log_entries_pkey ON auth.audit_log_entries USING btree (id)"},{"name":"audit_logs_instance_id_idx","definition":"CREATE INDEX audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"audit_log_entries_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"custom_oauth_providers","schema":"auth","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"provider_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"identifier","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_secret","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"acceptable_client_ids","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"scopes","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"pkce_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"attribute_mapping","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"authorization_params","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"email_optional","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"issuer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"discovery_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"skip_nonce_check","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"cached_discovery","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"discovery_cached_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"authorization_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"token_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"userinfo_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"jwks_uri","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"custom_claims_allowlist","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"custom_oauth_providers_created_at_idx","definition":"CREATE INDEX custom_oauth_providers_created_at_idx ON auth.custom_oauth_providers USING btree (created_at)"},{"name":"custom_oauth_providers_enabled_idx","definition":"CREATE INDEX custom_oauth_providers_enabled_idx ON auth.custom_oauth_providers USING btree (enabled)"},{"name":"custom_oauth_providers_identifier_idx","definition":"CREATE INDEX custom_oauth_providers_identifier_idx ON auth.custom_oauth_providers USING btree (identifier)"},{"name":"custom_oauth_providers_identifier_key","definition":"CREATE UNIQUE INDEX custom_oauth_providers_identifier_key ON auth.custom_oauth_providers USING btree (identifier)"},{"name":"custom_oauth_providers_pkey","definition":"CREATE UNIQUE INDEX custom_oauth_providers_pkey ON auth.custom_oauth_providers USING btree (id)"},{"name":"custom_oauth_providers_provider_type_idx","definition":"CREATE INDEX custom_oauth_providers_provider_type_idx ON auth.custom_oauth_providers USING btree (provider_type)"}],"policies":[],"triggers":[],"constraints":[{"name":"custom_oauth_providers_authorization_url_https","definition":"CHECK (authorization_url IS NULL OR authorization_url ~~ 'https://%'::text)"},{"name":"custom_oauth_providers_authorization_url_length","definition":"CHECK (authorization_url IS NULL OR char_length(authorization_url) <= 2048)"},{"name":"custom_oauth_providers_client_id_length","definition":"CHECK (char_length(client_id) >= 1 AND char_length(client_id) <= 512)"},{"name":"custom_oauth_providers_discovery_url_length","definition":"CHECK (discovery_url IS NULL OR char_length(discovery_url) <= 2048)"},{"name":"custom_oauth_providers_identifier_format","definition":"CHECK (identifier ~ '^[a-z0-9][a-z0-9:-]{0,48}[a-z0-9]$'::text)"},{"name":"custom_oauth_providers_identifier_key","definition":"UNIQUE (identifier)"},{"name":"custom_oauth_providers_issuer_length","definition":"CHECK (issuer IS NULL OR char_length(issuer) >= 1 AND char_length(issuer) <= 2048)"},{"name":"custom_oauth_providers_jwks_uri_https","definition":"CHECK (jwks_uri IS NULL OR jwks_uri ~~ 'https://%'::text)"},{"name":"custom_oauth_providers_jwks_uri_length","definition":"CHECK (jwks_uri IS NULL OR char_length(jwks_uri) <= 2048)"},{"name":"custom_oauth_providers_name_length","definition":"CHECK (char_length(name) >= 1 AND char_length(name) <= 100)"},{"name":"custom_oauth_providers_oauth2_requires_endpoints","definition":"CHECK (provider_type <> 'oauth2'::text OR authorization_url IS NOT NULL AND token_url IS NOT NULL AND userinfo_url IS NOT NULL)"},{"name":"custom_oauth_providers_oidc_discovery_url_https","definition":"CHECK (provider_type <> 'oidc'::text OR discovery_url IS NULL OR discovery_url ~~ 'https://%'::text)"},{"name":"custom_oauth_providers_oidc_issuer_https","definition":"CHECK (provider_type <> 'oidc'::text OR issuer IS NULL OR issuer ~~ 'https://%'::text)"},{"name":"custom_oauth_providers_oidc_requires_issuer","definition":"CHECK (provider_type <> 'oidc'::text OR issuer IS NOT NULL)"},{"name":"custom_oauth_providers_pkey","definition":"PRIMARY KEY (id)"},{"name":"custom_oauth_providers_provider_type_check","definition":"CHECK (provider_type = ANY (ARRAY['oauth2'::text, 'oidc'::text]))"},{"name":"custom_oauth_providers_token_url_https","definition":"CHECK (token_url IS NULL OR token_url ~~ 'https://%'::text)"},{"name":"custom_oauth_providers_token_url_length","definition":"CHECK (token_url IS NULL OR char_length(token_url) <= 2048)"},{"name":"custom_oauth_providers_userinfo_url_https","definition":"CHECK (userinfo_url IS NULL OR userinfo_url ~~ 'https://%'::text)"},{"name":"custom_oauth_providers_userinfo_url_length","definition":"CHECK (userinfo_url IS NULL OR char_length(userinfo_url) <= 2048)"}]},{"table":"flow_state","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"auth_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"code_challenge_method","type":"code_challenge_method","default":null,"identity":"","not_null":false,"generated":""},{"name":"code_challenge","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_access_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_refresh_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"authentication_method","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"auth_code_issued_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"invite_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"oauth_client_state_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"linking_target_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"email_optional","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"flow_state_created_at_idx","definition":"CREATE INDEX flow_state_created_at_idx ON auth.flow_state USING btree (created_at DESC)"},{"name":"flow_state_pkey","definition":"CREATE UNIQUE INDEX flow_state_pkey ON auth.flow_state USING btree (id)"},{"name":"idx_auth_code","definition":"CREATE INDEX idx_auth_code ON auth.flow_state USING btree (auth_code)"},{"name":"idx_user_id_auth_method","definition":"CREATE INDEX idx_user_id_auth_method ON auth.flow_state USING btree (user_id, authentication_method)"}],"policies":[],"triggers":[],"constraints":[{"name":"flow_state_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"identities","schema":"auth","columns":[{"name":"provider_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"identity_data","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"last_sign_in_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":"lower((identity_data ->> 'email'::text))","identity":"","not_null":false,"generated":"s"},{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"identities_email_idx","definition":"CREATE INDEX identities_email_idx ON auth.identities USING btree (email text_pattern_ops)"},{"name":"identities_pkey","definition":"CREATE UNIQUE INDEX identities_pkey ON auth.identities USING btree (id)"},{"name":"identities_provider_id_provider_unique","definition":"CREATE UNIQUE INDEX identities_provider_id_provider_unique ON auth.identities USING btree (provider_id, provider)"},{"name":"identities_user_id_idx","definition":"CREATE INDEX identities_user_id_idx ON auth.identities USING btree (user_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"identities_pkey","definition":"PRIMARY KEY (id)"},{"name":"identities_provider_id_provider_unique","definition":"UNIQUE (provider_id, provider)"},{"name":"identities_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"instances","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"uuid","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_base_config","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"instances_pkey","definition":"CREATE UNIQUE INDEX instances_pkey ON auth.instances USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"instances_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"mfa_amr_claims","schema":"auth","columns":[{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"authentication_method","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"amr_id_pk","definition":"CREATE UNIQUE INDEX amr_id_pk ON auth.mfa_amr_claims USING btree (id)"},{"name":"mfa_amr_claims_session_id_authentication_method_pkey","definition":"CREATE UNIQUE INDEX mfa_amr_claims_session_id_authentication_method_pkey ON auth.mfa_amr_claims USING btree (session_id, authentication_method)"}],"policies":[],"triggers":[],"constraints":[{"name":"amr_id_pk","definition":"PRIMARY KEY (id)"},{"name":"mfa_amr_claims_session_id_authentication_method_pkey","definition":"UNIQUE (session_id, authentication_method)"},{"name":"mfa_amr_claims_session_id_fkey","definition":"FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE"}]},{"table":"mfa_challenges","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"factor_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"inet","default":null,"identity":"","not_null":true,"generated":""},{"name":"otp_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"web_authn_session_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"mfa_challenge_created_at_idx","definition":"CREATE INDEX mfa_challenge_created_at_idx ON auth.mfa_challenges USING btree (created_at DESC)"},{"name":"mfa_challenges_pkey","definition":"CREATE UNIQUE INDEX mfa_challenges_pkey ON auth.mfa_challenges USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"mfa_challenges_auth_factor_id_fkey","definition":"FOREIGN KEY (factor_id) REFERENCES mfa_factors(id) ON DELETE CASCADE"},{"name":"mfa_challenges_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"mfa_factors","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"friendly_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"factor_type","type":"factor_type","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"factor_status","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"secret","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_challenged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"web_authn_credential","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"web_authn_aaguid","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_webauthn_challenge_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"factor_id_created_at_idx","definition":"CREATE INDEX factor_id_created_at_idx ON auth.mfa_factors USING btree (user_id, created_at)"},{"name":"mfa_factors_last_challenged_at_key","definition":"CREATE UNIQUE INDEX mfa_factors_last_challenged_at_key ON auth.mfa_factors USING btree (last_challenged_at)"},{"name":"mfa_factors_pkey","definition":"CREATE UNIQUE INDEX mfa_factors_pkey ON auth.mfa_factors USING btree (id)"},{"name":"mfa_factors_user_friendly_name_unique","definition":"CREATE UNIQUE INDEX mfa_factors_user_friendly_name_unique ON auth.mfa_factors USING btree (friendly_name, user_id) WHERE (TRIM(BOTH FROM friendly_name) <> ''::text)"},{"name":"mfa_factors_user_id_idx","definition":"CREATE INDEX mfa_factors_user_id_idx ON auth.mfa_factors USING btree (user_id)"},{"name":"unique_phone_factor_per_user","definition":"CREATE UNIQUE INDEX unique_phone_factor_per_user ON auth.mfa_factors USING btree (user_id, phone)"}],"policies":[],"triggers":[],"constraints":[{"name":"mfa_factors_last_challenged_at_key","definition":"UNIQUE (last_challenged_at)"},{"name":"mfa_factors_pkey","definition":"PRIMARY KEY (id)"},{"name":"mfa_factors_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"oauth_authorizations","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"authorization_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"redirect_uri","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scope","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resource","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"code_challenge","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"code_challenge_method","type":"code_challenge_method","default":null,"identity":"","not_null":false,"generated":""},{"name":"response_type","type":"oauth_response_type","default":"'code'::oauth_response_type","identity":"","not_null":true,"generated":""},{"name":"status","type":"oauth_authorization_status","default":"'pending'::oauth_authorization_status","identity":"","not_null":true,"generated":""},{"name":"authorization_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":"(now() + '00:03:00'::interval)","identity":"","not_null":true,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"nonce","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"oauth_auth_pending_exp_idx","definition":"CREATE INDEX oauth_auth_pending_exp_idx ON auth.oauth_authorizations USING btree (expires_at) WHERE (status = 'pending'::oauth_authorization_status)"},{"name":"oauth_authorizations_authorization_code_key","definition":"CREATE UNIQUE INDEX oauth_authorizations_authorization_code_key ON auth.oauth_authorizations USING btree (authorization_code)"},{"name":"oauth_authorizations_authorization_id_key","definition":"CREATE UNIQUE INDEX oauth_authorizations_authorization_id_key ON auth.oauth_authorizations USING btree (authorization_id)"},{"name":"oauth_authorizations_pkey","definition":"CREATE UNIQUE INDEX oauth_authorizations_pkey ON auth.oauth_authorizations USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"oauth_authorizations_authorization_code_key","definition":"UNIQUE (authorization_code)"},{"name":"oauth_authorizations_authorization_code_length","definition":"CHECK (char_length(authorization_code) <= 255)"},{"name":"oauth_authorizations_authorization_id_key","definition":"UNIQUE (authorization_id)"},{"name":"oauth_authorizations_client_id_fkey","definition":"FOREIGN KEY (client_id) REFERENCES oauth_clients(id) ON DELETE CASCADE"},{"name":"oauth_authorizations_code_challenge_length","definition":"CHECK (char_length(code_challenge) <= 128)"},{"name":"oauth_authorizations_expires_at_future","definition":"CHECK (expires_at > created_at)"},{"name":"oauth_authorizations_nonce_length","definition":"CHECK (char_length(nonce) <= 255)"},{"name":"oauth_authorizations_pkey","definition":"PRIMARY KEY (id)"},{"name":"oauth_authorizations_redirect_uri_length","definition":"CHECK (char_length(redirect_uri) <= 2048)"},{"name":"oauth_authorizations_resource_length","definition":"CHECK (char_length(resource) <= 2048)"},{"name":"oauth_authorizations_scope_length","definition":"CHECK (char_length(scope) <= 4096)"},{"name":"oauth_authorizations_state_length","definition":"CHECK (char_length(state) <= 4096)"},{"name":"oauth_authorizations_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"oauth_client_states","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"code_verifier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_oauth_client_states_created_at","definition":"CREATE INDEX idx_oauth_client_states_created_at ON auth.oauth_client_states USING btree (created_at)"},{"name":"oauth_client_states_pkey","definition":"CREATE UNIQUE INDEX oauth_client_states_pkey ON auth.oauth_client_states USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"oauth_client_states_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"oauth_clients","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_secret_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"registration_type","type":"oauth_registration_type","default":null,"identity":"","not_null":true,"generated":""},{"name":"redirect_uris","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"grant_types","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"client_uri","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"logo_uri","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"client_type","type":"oauth_client_type","default":"'confidential'::oauth_client_type","identity":"","not_null":true,"generated":""},{"name":"token_endpoint_auth_method","type":"text","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"oauth_clients_deleted_at_idx","definition":"CREATE INDEX oauth_clients_deleted_at_idx ON auth.oauth_clients USING btree (deleted_at)"},{"name":"oauth_clients_pkey","definition":"CREATE UNIQUE INDEX oauth_clients_pkey ON auth.oauth_clients USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"oauth_clients_client_name_length","definition":"CHECK (char_length(client_name) <= 1024)"},{"name":"oauth_clients_client_uri_length","definition":"CHECK (char_length(client_uri) <= 2048)"},{"name":"oauth_clients_logo_uri_length","definition":"CHECK (char_length(logo_uri) <= 2048)"},{"name":"oauth_clients_pkey","definition":"PRIMARY KEY (id)"},{"name":"oauth_clients_token_endpoint_auth_method_check","definition":"CHECK (token_endpoint_auth_method = ANY (ARRAY['client_secret_basic'::text, 'client_secret_post'::text, 'none'::text]))"}]},{"table":"oauth_consents","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"scopes","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"granted_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"oauth_consents_active_client_idx","definition":"CREATE INDEX oauth_consents_active_client_idx ON auth.oauth_consents USING btree (client_id) WHERE (revoked_at IS NULL)"},{"name":"oauth_consents_active_user_client_idx","definition":"CREATE INDEX oauth_consents_active_user_client_idx ON auth.oauth_consents USING btree (user_id, client_id) WHERE (revoked_at IS NULL)"},{"name":"oauth_consents_pkey","definition":"CREATE UNIQUE INDEX oauth_consents_pkey ON auth.oauth_consents USING btree (id)"},{"name":"oauth_consents_user_client_unique","definition":"CREATE UNIQUE INDEX oauth_consents_user_client_unique ON auth.oauth_consents USING btree (user_id, client_id)"},{"name":"oauth_consents_user_order_idx","definition":"CREATE INDEX oauth_consents_user_order_idx ON auth.oauth_consents USING btree (user_id, granted_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"oauth_consents_client_id_fkey","definition":"FOREIGN KEY (client_id) REFERENCES oauth_clients(id) ON DELETE CASCADE"},{"name":"oauth_consents_pkey","definition":"PRIMARY KEY (id)"},{"name":"oauth_consents_revoked_after_granted","definition":"CHECK (revoked_at IS NULL OR revoked_at >= granted_at)"},{"name":"oauth_consents_scopes_length","definition":"CHECK (char_length(scopes) <= 2048)"},{"name":"oauth_consents_scopes_not_empty","definition":"CHECK (char_length(TRIM(BOTH FROM scopes)) > 0)"},{"name":"oauth_consents_user_client_unique","definition":"UNIQUE (user_id, client_id)"},{"name":"oauth_consents_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"one_time_tokens","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"token_type","type":"one_time_token_type","default":null,"identity":"","not_null":true,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"relates_to","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp without time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp without time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"one_time_tokens_pkey","definition":"CREATE UNIQUE INDEX one_time_tokens_pkey ON auth.one_time_tokens USING btree (id)"},{"name":"one_time_tokens_relates_to_hash_idx","definition":"CREATE INDEX one_time_tokens_relates_to_hash_idx ON auth.one_time_tokens USING hash (relates_to)"},{"name":"one_time_tokens_token_hash_hash_idx","definition":"CREATE INDEX one_time_tokens_token_hash_hash_idx ON auth.one_time_tokens USING hash (token_hash)"},{"name":"one_time_tokens_user_id_token_type_key","definition":"CREATE UNIQUE INDEX one_time_tokens_user_id_token_type_key ON auth.one_time_tokens USING btree (user_id, token_type)"}],"policies":[],"triggers":[],"constraints":[{"name":"one_time_tokens_pkey","definition":"PRIMARY KEY (id)"},{"name":"one_time_tokens_token_hash_check","definition":"CHECK (char_length(token_hash) > 0)"},{"name":"one_time_tokens_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"refresh_tokens","schema":"auth","columns":[{"name":"instance_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"id","type":"bigint","default":"nextval('refresh_tokens_id_seq'::regclass)","identity":"","not_null":true,"generated":""},{"name":"token","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"parent","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"refresh_tokens_instance_id_idx","definition":"CREATE INDEX refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id)"},{"name":"refresh_tokens_instance_id_user_id_idx","definition":"CREATE INDEX refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id)"},{"name":"refresh_tokens_parent_idx","definition":"CREATE INDEX refresh_tokens_parent_idx ON auth.refresh_tokens USING btree (parent)"},{"name":"refresh_tokens_pkey","definition":"CREATE UNIQUE INDEX refresh_tokens_pkey ON auth.refresh_tokens USING btree (id)"},{"name":"refresh_tokens_session_id_revoked_idx","definition":"CREATE INDEX refresh_tokens_session_id_revoked_idx ON auth.refresh_tokens USING btree (session_id, revoked)"},{"name":"refresh_tokens_token_unique","definition":"CREATE UNIQUE INDEX refresh_tokens_token_unique ON auth.refresh_tokens USING btree (token)"},{"name":"refresh_tokens_updated_at_idx","definition":"CREATE INDEX refresh_tokens_updated_at_idx ON auth.refresh_tokens USING btree (updated_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"refresh_tokens_pkey","definition":"PRIMARY KEY (id)"},{"name":"refresh_tokens_session_id_fkey","definition":"FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE"},{"name":"refresh_tokens_token_unique","definition":"UNIQUE (token)"}]},{"table":"saml_providers","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"sso_provider_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata_xml","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"attribute_mapping","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"name_id_format","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"saml_providers_entity_id_key","definition":"CREATE UNIQUE INDEX saml_providers_entity_id_key ON auth.saml_providers USING btree (entity_id)"},{"name":"saml_providers_pkey","definition":"CREATE UNIQUE INDEX saml_providers_pkey ON auth.saml_providers USING btree (id)"},{"name":"saml_providers_sso_provider_id_idx","definition":"CREATE INDEX saml_providers_sso_provider_id_idx ON auth.saml_providers USING btree (sso_provider_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"entity_id not empty","definition":"CHECK (char_length(entity_id) > 0)"},{"name":"metadata_url not empty","definition":"CHECK (metadata_url = NULL::text OR char_length(metadata_url) > 0)"},{"name":"metadata_xml not empty","definition":"CHECK (char_length(metadata_xml) > 0)"},{"name":"saml_providers_entity_id_key","definition":"UNIQUE (entity_id)"},{"name":"saml_providers_pkey","definition":"PRIMARY KEY (id)"},{"name":"saml_providers_sso_provider_id_fkey","definition":"FOREIGN KEY (sso_provider_id) REFERENCES sso_providers(id) ON DELETE CASCADE"}]},{"table":"saml_relay_states","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"sso_provider_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"request_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"for_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"redirect_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"flow_state_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"saml_relay_states_created_at_idx","definition":"CREATE INDEX saml_relay_states_created_at_idx ON auth.saml_relay_states USING btree (created_at DESC)"},{"name":"saml_relay_states_for_email_idx","definition":"CREATE INDEX saml_relay_states_for_email_idx ON auth.saml_relay_states USING btree (for_email)"},{"name":"saml_relay_states_pkey","definition":"CREATE UNIQUE INDEX saml_relay_states_pkey ON auth.saml_relay_states USING btree (id)"},{"name":"saml_relay_states_sso_provider_id_idx","definition":"CREATE INDEX saml_relay_states_sso_provider_id_idx ON auth.saml_relay_states USING btree (sso_provider_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"request_id not empty","definition":"CHECK (char_length(request_id) > 0)"},{"name":"saml_relay_states_flow_state_id_fkey","definition":"FOREIGN KEY (flow_state_id) REFERENCES flow_state(id) ON DELETE CASCADE"},{"name":"saml_relay_states_pkey","definition":"PRIMARY KEY (id)"},{"name":"saml_relay_states_sso_provider_id_fkey","definition":"FOREIGN KEY (sso_provider_id) REFERENCES sso_providers(id) ON DELETE CASCADE"}]},{"table":"schema_migrations","schema":"auth","columns":[{"name":"version","type":"character varying(255)","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"schema_migrations_pkey","definition":"CREATE UNIQUE INDEX schema_migrations_pkey ON auth.schema_migrations USING btree (version)"}],"policies":[],"triggers":[],"constraints":[{"name":"schema_migrations_pkey","definition":"PRIMARY KEY (version)"}]},{"table":"sessions","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"factor_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"aal","type":"aal_level","default":null,"identity":"","not_null":false,"generated":""},{"name":"not_after","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"refreshed_at","type":"timestamp without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip","type":"inet","default":null,"identity":"","not_null":false,"generated":""},{"name":"tag","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"oauth_client_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"refresh_token_hmac_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"refresh_token_counter","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"scopes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"sessions_not_after_idx","definition":"CREATE INDEX sessions_not_after_idx ON auth.sessions USING btree (not_after DESC)"},{"name":"sessions_oauth_client_id_idx","definition":"CREATE INDEX sessions_oauth_client_id_idx ON auth.sessions USING btree (oauth_client_id)"},{"name":"sessions_pkey","definition":"CREATE UNIQUE INDEX sessions_pkey ON auth.sessions USING btree (id)"},{"name":"sessions_user_id_idx","definition":"CREATE INDEX sessions_user_id_idx ON auth.sessions USING btree (user_id)"},{"name":"user_id_created_at_idx","definition":"CREATE INDEX user_id_created_at_idx ON auth.sessions USING btree (user_id, created_at)"}],"policies":[],"triggers":[],"constraints":[{"name":"sessions_oauth_client_id_fkey","definition":"FOREIGN KEY (oauth_client_id) REFERENCES oauth_clients(id) ON DELETE CASCADE"},{"name":"sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"sessions_scopes_length","definition":"CHECK (char_length(scopes) <= 4096)"},{"name":"sessions_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"sso_domains","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"sso_provider_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"domain","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"sso_domains_domain_idx","definition":"CREATE UNIQUE INDEX sso_domains_domain_idx ON auth.sso_domains USING btree (lower(domain))"},{"name":"sso_domains_pkey","definition":"CREATE UNIQUE INDEX sso_domains_pkey ON auth.sso_domains USING btree (id)"},{"name":"sso_domains_sso_provider_id_idx","definition":"CREATE INDEX sso_domains_sso_provider_id_idx ON auth.sso_domains USING btree (sso_provider_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"domain not empty","definition":"CHECK (char_length(domain) > 0)"},{"name":"sso_domains_pkey","definition":"PRIMARY KEY (id)"},{"name":"sso_domains_sso_provider_id_fkey","definition":"FOREIGN KEY (sso_provider_id) REFERENCES sso_providers(id) ON DELETE CASCADE"}]},{"table":"sso_providers","schema":"auth","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"resource_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"disabled","type":"boolean","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"sso_providers_pkey","definition":"CREATE UNIQUE INDEX sso_providers_pkey ON auth.sso_providers USING btree (id)"},{"name":"sso_providers_resource_id_idx","definition":"CREATE UNIQUE INDEX sso_providers_resource_id_idx ON auth.sso_providers USING btree (lower(resource_id))"},{"name":"sso_providers_resource_id_pattern_idx","definition":"CREATE INDEX sso_providers_resource_id_pattern_idx ON auth.sso_providers USING btree (resource_id text_pattern_ops)"}],"policies":[],"triggers":[],"constraints":[{"name":"resource_id not empty","definition":"CHECK (resource_id = NULL::text OR char_length(resource_id) > 0)"},{"name":"sso_providers_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"users","schema":"auth","columns":[{"name":"instance_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"aud","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"encrypted_password","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"email_confirmed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"invited_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"confirmation_token","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"confirmation_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"recovery_token","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"recovery_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"email_change_token_new","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"email_change","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"email_change_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_sign_in_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_app_meta_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_user_meta_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_super_admin","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":"NULL::character varying","identity":"","not_null":false,"generated":""},{"name":"phone_confirmed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_change","type":"text","default":"''::character varying","identity":"","not_null":false,"generated":""},{"name":"phone_change_token","type":"character varying(255)","default":"''::character varying","identity":"","not_null":false,"generated":""},{"name":"phone_change_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"confirmed_at","type":"timestamp with time zone","default":"LEAST(email_confirmed_at, phone_confirmed_at)","identity":"","not_null":false,"generated":"s"},{"name":"email_change_token_current","type":"character varying(255)","default":"''::character varying","identity":"","not_null":false,"generated":""},{"name":"email_change_confirm_status","type":"smallint","default":"0","identity":"","not_null":false,"generated":""},{"name":"banned_until","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reauthentication_token","type":"character varying(255)","default":"''::character varying","identity":"","not_null":false,"generated":""},{"name":"reauthentication_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_sso_user","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_anonymous","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"confirmation_token_idx","definition":"CREATE UNIQUE INDEX confirmation_token_idx ON auth.users USING btree (confirmation_token) WHERE ((confirmation_token)::text !~ '^[0-9 ]*$'::text)"},{"name":"email_change_token_current_idx","definition":"CREATE UNIQUE INDEX email_change_token_current_idx ON auth.users USING btree (email_change_token_current) WHERE ((email_change_token_current)::text !~ '^[0-9 ]*$'::text)"},{"name":"email_change_token_new_idx","definition":"CREATE UNIQUE INDEX email_change_token_new_idx ON auth.users USING btree (email_change_token_new) WHERE ((email_change_token_new)::text !~ '^[0-9 ]*$'::text)"},{"name":"idx_users_created_at_desc","definition":"CREATE INDEX idx_users_created_at_desc ON auth.users USING btree (created_at DESC)"},{"name":"idx_users_email","definition":"CREATE INDEX idx_users_email ON auth.users USING btree (email)"},{"name":"idx_users_last_sign_in_at_desc","definition":"CREATE INDEX idx_users_last_sign_in_at_desc ON auth.users USING btree (last_sign_in_at DESC)"},{"name":"idx_users_name","definition":"CREATE INDEX idx_users_name ON auth.users USING btree (((raw_user_meta_data ->> 'name'::text))) WHERE ((raw_user_meta_data ->> 'name'::text) IS NOT NULL)"},{"name":"reauthentication_token_idx","definition":"CREATE UNIQUE INDEX reauthentication_token_idx ON auth.users USING btree (reauthentication_token) WHERE ((reauthentication_token)::text !~ '^[0-9 ]*$'::text)"},{"name":"recovery_token_idx","definition":"CREATE UNIQUE INDEX recovery_token_idx ON auth.users USING btree (recovery_token) WHERE ((recovery_token)::text !~ '^[0-9 ]*$'::text)"},{"name":"users_email_partial_key","definition":"CREATE UNIQUE INDEX users_email_partial_key ON auth.users USING btree (email) WHERE (is_sso_user = false)"},{"name":"users_instance_id_email_idx","definition":"CREATE INDEX users_instance_id_email_idx ON auth.users USING btree (instance_id, lower((email)::text))"},{"name":"users_instance_id_idx","definition":"CREATE INDEX users_instance_id_idx ON auth.users USING btree (instance_id)"},{"name":"users_is_anonymous_idx","definition":"CREATE INDEX users_is_anonymous_idx ON auth.users USING btree (is_anonymous)"},{"name":"users_phone_key","definition":"CREATE UNIQUE INDEX users_phone_key ON auth.users USING btree (phone)"},{"name":"users_pkey","definition":"CREATE UNIQUE INDEX users_pkey ON auth.users USING btree (id)"}],"policies":[],"triggers":[{"name":"trg_knocklaunch_auth_delete_to_profile","definition":"CREATE TRIGGER trg_knocklaunch_auth_delete_to_profile AFTER DELETE ON users FOR EACH ROW EXECUTE FUNCTION knocklaunch_sync_auth_delete_to_profile()"}],"constraints":[{"name":"users_email_change_confirm_status_check","definition":"CHECK (email_change_confirm_status >= 0 AND email_change_confirm_status <= 2)"},{"name":"users_phone_key","definition":"UNIQUE (phone)"},{"name":"users_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"webauthn_challenges","schema":"auth","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"challenge_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"session_data","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"webauthn_challenges_expires_at_idx","definition":"CREATE INDEX webauthn_challenges_expires_at_idx ON auth.webauthn_challenges USING btree (expires_at)"},{"name":"webauthn_challenges_pkey","definition":"CREATE UNIQUE INDEX webauthn_challenges_pkey ON auth.webauthn_challenges USING btree (id)"},{"name":"webauthn_challenges_user_id_idx","definition":"CREATE INDEX webauthn_challenges_user_id_idx ON auth.webauthn_challenges USING btree (user_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"webauthn_challenges_challenge_type_check","definition":"CHECK (challenge_type = ANY (ARRAY['signup'::text, 'registration'::text, 'authentication'::text]))"},{"name":"webauthn_challenges_pkey","definition":"PRIMARY KEY (id)"},{"name":"webauthn_challenges_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"webauthn_credentials","schema":"auth","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"credential_id","type":"bytea","default":null,"identity":"","not_null":true,"generated":""},{"name":"public_key","type":"bytea","default":null,"identity":"","not_null":true,"generated":""},{"name":"attestation_type","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"aaguid","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"sign_count","type":"bigint","default":"0","identity":"","not_null":true,"generated":""},{"name":"transports","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"backup_eligible","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"backed_up","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"friendly_name","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"last_used_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"webauthn_credentials_credential_id_key","definition":"CREATE UNIQUE INDEX webauthn_credentials_credential_id_key ON auth.webauthn_credentials USING btree (credential_id)"},{"name":"webauthn_credentials_pkey","definition":"CREATE UNIQUE INDEX webauthn_credentials_pkey ON auth.webauthn_credentials USING btree (id)"},{"name":"webauthn_credentials_user_id_idx","definition":"CREATE INDEX webauthn_credentials_user_id_idx ON auth.webauthn_credentials USING btree (user_id)"}],"policies":[],"triggers":[],"constraints":[{"name":"webauthn_credentials_pkey","definition":"PRIMARY KEY (id)"},{"name":"webauthn_credentials_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"academy_app_actions","schema":"public","columns":[{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"default_route","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_app_actions_pkey","definition":"CREATE UNIQUE INDEX academy_app_actions_pkey ON public.academy_app_actions USING btree (key)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_app_actions","permissive":"PERMISSIVE","policyname":"auth read app_actions","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_app_actions","permissive":"PERMISSIVE","policyname":"godmode write app_actions","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_app_actions_pkey","definition":"PRIMARY KEY (key)"}]},{"table":"academy_assignment_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_required","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"due_days","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_assignment_rules_pkey","definition":"CREATE UNIQUE INDEX academy_assignment_rules_pkey ON public.academy_assignment_rules USING btree (id)"},{"name":"academy_assignment_rules_tenant_org_id_course_id_role_key","definition":"CREATE UNIQUE INDEX academy_assignment_rules_tenant_org_id_course_id_role_key ON public.academy_assignment_rules USING btree (tenant_org_id, course_id, role)"},{"name":"idx_academy_assignment_rules_role","definition":"CREATE INDEX idx_academy_assignment_rules_role ON public.academy_assignment_rules USING btree (tenant_org_id, role)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IS NOT NULL)","roles":["authenticated"],"tablename":"academy_assignment_rules","permissive":"RESTRICTIVE","policyname":"block null tenant rules","schemaname":"public","with_check":"(tenant_org_id IS NOT NULL)"},{"cmd":"ALL","qual":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_assignment_rules","permissive":"PERMISSIVE","policyname":"owners write rules","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_assignment_rules","permissive":"PERMISSIVE","policyname":"tenant members read rules","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_assignment_rules_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_assignment_rules_tenant_org_id_course_id_role_key","definition":"UNIQUE (tenant_org_id, course_id, role)"}]},{"table":"academy_badge_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"badge_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metric","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"threshold","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_badge_rules_badge_key_key","definition":"CREATE UNIQUE INDEX academy_badge_rules_badge_key_key ON public.academy_badge_rules USING btree (badge_key)"},{"name":"academy_badge_rules_pkey","definition":"CREATE UNIQUE INDEX academy_badge_rules_pkey ON public.academy_badge_rules USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_badge_rules","permissive":"PERMISSIVE","policyname":"Admins manage badge rules","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_badge_rules","permissive":"PERMISSIVE","policyname":"Anyone can view badge rules","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_badge_rules_badge_key_key","definition":"UNIQUE (badge_key)"},{"name":"academy_badge_rules_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_badges","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"badge_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"icon","type":"text","default":"'🏆'::text","identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":"'general'::text","identity":"","not_null":false,"generated":""},{"name":"points_required","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_badges_badge_key_key","definition":"CREATE UNIQUE INDEX academy_badges_badge_key_key ON public.academy_badges USING btree (badge_key)"},{"name":"academy_badges_pkey","definition":"CREATE UNIQUE INDEX academy_badges_pkey ON public.academy_badges USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"academy_badges","permissive":"PERMISSIVE","policyname":"Admins can manage badges","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"true","roles":["public"],"tablename":"academy_badges","permissive":"PERMISSIVE","policyname":"Anyone can view badges","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_badges_badge_key_key","definition":"UNIQUE (badge_key)"},{"name":"academy_badges_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_certificate_recipients","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"certificate_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"recipient_role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"recipient_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"email_status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"queued_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_certificate_recipients_pkey","definition":"CREATE UNIQUE INDEX academy_certificate_recipients_pkey ON public.academy_certificate_recipients USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM academy_certificates c\n  WHERE ((c.id = academy_certificate_recipients.certificate_id) AND ((c.user_id = uid()) OR is_tenant_owner_for(uid(), c.tenant_org_id) OR is_system_admin(uid())))))","roles":["authenticated"],"tablename":"academy_certificate_recipients","permissive":"PERMISSIVE","policyname":"Certificate recipients readable by proof viewers","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_certificate_recipients","permissive":"PERMISSIVE","policyname":"GodMode manages certificate recipients","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_certificate_recipients_certificate_id_fkey","definition":"FOREIGN KEY (certificate_id) REFERENCES academy_certificates(id) ON DELETE CASCADE"},{"name":"academy_certificate_recipients_email_status_check","definition":"CHECK (email_status = ANY (ARRAY['pending'::text, 'sent'::text, 'failed'::text, 'skipped'::text]))"},{"name":"academy_certificate_recipients_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_certificate_recipients_recipient_role_check","definition":"CHECK (recipient_role = ANY (ARRAY['user'::text, 'tenant_owner'::text, 'godmode'::text]))"}]},{"table":"academy_certificates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"certificate_number","type":"text","default":"('KL-ACADEMY-'::text || upper(replace((gen_random_uuid())::text, '-'::text, ''::text)))","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"certificate_title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"issued_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"issued_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_certificates_certificate_number_key","definition":"CREATE UNIQUE INDEX academy_certificates_certificate_number_key ON public.academy_certificates USING btree (certificate_number)"},{"name":"academy_certificates_pkey","definition":"CREATE UNIQUE INDEX academy_certificates_pkey ON public.academy_certificates USING btree (id)"},{"name":"academy_certificates_tenant_org_id_user_id_course_id_key","definition":"CREATE UNIQUE INDEX academy_certificates_tenant_org_id_user_id_course_id_key ON public.academy_certificates USING btree (tenant_org_id, user_id, course_id)"},{"name":"idx_academy_certificates_tenant","definition":"CREATE INDEX idx_academy_certificates_tenant ON public.academy_certificates USING btree (tenant_org_id, issued_at DESC)"},{"name":"idx_academy_certificates_user","definition":"CREATE INDEX idx_academy_certificates_user ON public.academy_certificates USING btree (user_id, issued_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"academy_certificates","permissive":"PERMISSIVE","policyname":"System inserts Academy certificates","schemaname":"public","with_check":"((user_id = uid()) OR is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_certificates","permissive":"PERMISSIVE","policyname":"Users and owners read Academy certificates","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_certificates_certificate_number_key","definition":"UNIQUE (certificate_number)"},{"name":"academy_certificates_course_id_fkey","definition":"FOREIGN KEY (course_id) REFERENCES academy_courses(id) ON DELETE CASCADE"},{"name":"academy_certificates_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_certificates_tenant_org_id_user_id_course_id_key","definition":"UNIQUE (tenant_org_id, user_id, course_id)"}]},{"table":"academy_change_notes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"audience","type":"text","default":"'all_users'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_course_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"published_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_published","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_change_notes_pkey","definition":"CREATE UNIQUE INDEX academy_change_notes_pkey ON public.academy_change_notes USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_change_notes","permissive":"PERMISSIVE","policyname":"GodMode manages Academy change notes","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((is_published = true) AND ((tenant_org_id IS NULL) OR is_tenant_member(tenant_org_id) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"academy_change_notes","permissive":"PERMISSIVE","policyname":"Published Academy change notes visible","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_change_notes_audience_check","definition":"CHECK (audience = ANY (ARRAY['all_users'::text, 'tenant_users'::text, 'owners'::text, 'managers'::text, 'reps'::text, 'crew'::text, 'godmode'::text]))"},{"name":"academy_change_notes_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_change_notes_related_course_id_fkey","definition":"FOREIGN KEY (related_course_id) REFERENCES academy_courses(id) ON DELETE SET NULL"},{"name":"academy_change_notes_related_module_key_fkey","definition":"FOREIGN KEY (related_module_key) REFERENCES academy_module_keys(key) ON DELETE SET NULL"}]},{"table":"academy_coaching_moments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"call_log_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"objection_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scenario_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roleplay_session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_coaching_moments_pkey","definition":"CREATE UNIQUE INDEX academy_coaching_moments_pkey ON public.academy_coaching_moments USING btree (id)"},{"name":"idx_acm_tenant","definition":"CREATE INDEX idx_acm_tenant ON public.academy_coaching_moments USING btree (tenant_org_id)"},{"name":"idx_acm_user_status","definition":"CREATE INDEX idx_acm_user_status ON public.academy_coaching_moments USING btree (user_id, status)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"academy_coaching_moments","permissive":"PERMISSIVE","policyname":"Users insert own coaching moments","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"academy_coaching_moments","permissive":"PERMISSIVE","policyname":"Users see own coaching moments","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"academy_coaching_moments","permissive":"PERMISSIVE","policyname":"Users update own coaching moments","schemaname":"public","with_check":"(user_id = uid())"}],"triggers":[],"constraints":[{"name":"academy_coaching_moments_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_compliance_gates","schema":"public","columns":[{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"gate_type","type":"text","default":"'phone_readiness'::text","identity":"","not_null":true,"generated":""},{"name":"required_course_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"required_certificate","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"enforcement_status","type":"text","default":"'report_only'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_compliance_gates_pkey","definition":"CREATE UNIQUE INDEX academy_compliance_gates_pkey ON public.academy_compliance_gates USING btree (key)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_compliance_gates","permissive":"PERMISSIVE","policyname":"Academy compliance gates readable","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_compliance_gates","permissive":"PERMISSIVE","policyname":"GodMode manages compliance gates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_compliance_gates_enforcement_status_check","definition":"CHECK (enforcement_status = ANY (ARRAY['report_only'::text, 'enforced'::text, 'disabled'::text]))"},{"name":"academy_compliance_gates_gate_type_check","definition":"CHECK (gate_type = ANY (ARRAY['phone_readiness'::text, 'sms_readiness'::text, 'crew_closeout'::text, 'pm_verification'::text, 'owner_launch'::text]))"},{"name":"academy_compliance_gates_pkey","definition":"PRIMARY KEY (key)"},{"name":"academy_compliance_gates_required_course_id_fkey","definition":"FOREIGN KEY (required_course_id) REFERENCES academy_courses(id) ON DELETE SET NULL"}]},{"table":"academy_content_blocks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"block_type","type":"text","default":"'rich_text'::text","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_content_blocks_pkey","definition":"CREATE UNIQUE INDEX academy_content_blocks_pkey ON public.academy_content_blocks USING btree (id)"},{"name":"idx_academy_content_blocks_lesson_order","definition":"CREATE INDEX idx_academy_content_blocks_lesson_order ON public.academy_content_blocks USING btree (lesson_id, order_index)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM ((academy_lessons l\n     JOIN academy_units u ON ((u.id = l.unit_id)))\n     JOIN academy_courses c ON ((c.id = u.course_id)))\n  WHERE ((l.id = academy_content_blocks.lesson_id) AND academy_course_visible(c.tenant_org_id, c.is_published))))","roles":["public"],"tablename":"academy_content_blocks","permissive":"PERMISSIVE","policyname":"Academy content blocks visible via lesson","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_content_blocks","permissive":"PERMISSIVE","policyname":"GodMode manages Academy content blocks","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_content_blocks_block_type_check","definition":"CHECK (block_type = ANY (ARRAY['rich_text'::text, 'callout'::text, 'checklist'::text, 'video'::text, 'route_link'::text, 'scenario_prompt'::text, 'glossary_terms'::text, 'change_note'::text, 'download'::text, 'sidekick_prompt'::text]))"},{"name":"academy_content_blocks_lesson_id_fkey","definition":"FOREIGN KEY (lesson_id) REFERENCES academy_lessons(id) ON DELETE CASCADE"},{"name":"academy_content_blocks_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_content_versions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"version","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"content_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_content_versions_pkey","definition":"CREATE UNIQUE INDEX academy_content_versions_pkey ON public.academy_content_versions USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_content_versions","permissive":"PERMISSIVE","policyname":"godmode write versions","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM academy_courses c\n  WHERE ((c.id = academy_content_versions.course_id) AND academy_course_visible(c.tenant_org_id, c.is_published)))))","roles":["public"],"tablename":"academy_content_versions","permissive":"PERMISSIVE","policyname":"tenant members read versions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_content_versions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_courses","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_track","type":"text","default":"'universal'::text","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'crm-fundamentals'::text","identity":"","not_null":true,"generated":""},{"name":"difficulty_level","type":"text","default":"'beginner'::text","identity":"","not_null":true,"generated":""},{"name":"estimated_duration_minutes","type":"integer","default":"30","identity":"","not_null":false,"generated":""},{"name":"thumbnail_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_published","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"scope","type":"text","default":"'tenant'::text","identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"required_roles","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"required_module_keys","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"is_required","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"content_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"superseded_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"review_status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"reviewed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"certifies","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"certificate_title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"compliance_gate_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"certificate_email_user","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"certificate_email_owner","type":"boolean","default":"true","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_courses_pkey","definition":"CREATE UNIQUE INDEX academy_courses_pkey ON public.academy_courses USING btree (id)"},{"name":"idx_academy_courses_compliance_gate","definition":"CREATE INDEX idx_academy_courses_compliance_gate ON public.academy_courses USING btree (compliance_gate_key) WHERE (compliance_gate_key IS NOT NULL)"},{"name":"idx_academy_courses_scope","definition":"CREATE INDEX idx_academy_courses_scope ON public.academy_courses USING btree (scope)"},{"name":"idx_academy_courses_scope_published","definition":"CREATE INDEX idx_academy_courses_scope_published ON public.academy_courses USING btree (scope, is_published, review_status)"},{"name":"idx_academy_courses_tenant_review","definition":"CREATE INDEX idx_academy_courses_tenant_review ON public.academy_courses USING btree (tenant_org_id, review_status)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(uid()) OR is_tenant_owner_for(uid(), tenant_org_id))","roles":["public"],"tablename":"academy_courses","permissive":"PERMISSIVE","policyname":"Admins can manage courses","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"academy_course_visible(tenant_org_id, is_published)","roles":["public"],"tablename":"academy_courses","permissive":"PERMISSIVE","policyname":"Members or universal can view published courses","schemaname":"public","with_check":null}],"triggers":[{"name":"update_academy_courses_updated_at","definition":"CREATE TRIGGER update_academy_courses_updated_at BEFORE UPDATE ON academy_courses FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_courses_category_check","definition":"CHECK (category = ANY (ARRAY['crm-fundamentals'::text, 'door-knocking'::text, 'cold-calling'::text, 'insurance-101'::text, 'industry-knowledge'::text, 'objection-handling'::text, 'closing'::text, 'compliance'::text, 'platform-mastery'::text, 'safety'::text, 'storm-report-presentation'::text, 'follow-up'::text, 'onboarding'::text]))"},{"name":"academy_courses_difficulty_level_check","definition":"CHECK (difficulty_level = ANY (ARRAY['beginner'::text, 'intermediate'::text, 'advanced'::text]))"},{"name":"academy_courses_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_courses_review_status_check","definition":"CHECK (review_status = ANY (ARRAY['active'::text, 'review_required'::text, 'retired'::text]))"},{"name":"academy_courses_scope_check","definition":"CHECK (scope = ANY (ARRAY['platform'::text, 'template'::text, 'tenant'::text]))"},{"name":"academy_courses_tenant_track_check","definition":"CHECK (tenant_track = ANY (ARRAY['mitigation'::text, 'roofing'::text, 'public_adjuster'::text, 'realtor'::text, 'universal'::text]))"}]},{"table":"academy_enrollments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"enrolled_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"progress_percent","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_enrollments_pkey","definition":"CREATE UNIQUE INDEX academy_enrollments_pkey ON public.academy_enrollments USING btree (id)"},{"name":"academy_enrollments_user_course_unique","definition":"CREATE UNIQUE INDEX academy_enrollments_user_course_unique ON public.academy_enrollments USING btree (user_id, course_id)"},{"name":"academy_enrollments_user_id_course_id_key","definition":"CREATE UNIQUE INDEX academy_enrollments_user_id_course_id_key ON public.academy_enrollments USING btree (user_id, course_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"academy_enrollments","permissive":"PERMISSIVE","policyname":"Admins can manage enrollments","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"can_view_tenant_member_academy(uid(), user_id)","roles":["public"],"tablename":"academy_enrollments","permissive":"PERMISSIVE","policyname":"Tenant owners manage member enrollments","schemaname":"public","with_check":"can_view_tenant_member_academy(uid(), user_id)"},{"cmd":"SELECT","qual":"can_view_tenant_member_academy(uid(), user_id)","roles":["public"],"tablename":"academy_enrollments","permissive":"PERMISSIVE","policyname":"Tenant owners view member enrollments","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"academy_enrollments","permissive":"PERMISSIVE","policyname":"Users can enroll themselves","schemaname":"public","with_check":"((uid() = user_id) OR (uid() = enrolled_by))"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_enrollments","permissive":"PERMISSIVE","policyname":"Users can update own enrollments","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_enrollments","permissive":"PERMISSIVE","policyname":"Users can view own enrollments","schemaname":"public","with_check":null}],"triggers":[{"name":"update_academy_enrollments_updated_at","definition":"CREATE TRIGGER update_academy_enrollments_updated_at BEFORE UPDATE ON academy_enrollments FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_enrollments_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_enrollments_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'completed'::text, 'dropped'::text]))"},{"name":"academy_enrollments_user_course_unique","definition":"UNIQUE (user_id, course_id)"},{"name":"academy_enrollments_user_id_course_id_key","definition":"UNIQUE (user_id, course_id)"}]},{"table":"academy_glossary_terms","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"term","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"plain_language_definition","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_track","type":"text","default":"'universal'::text","identity":"","not_null":true,"generated":""},{"name":"related_module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_course_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_published","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_glossary_terms_pkey","definition":"CREATE UNIQUE INDEX academy_glossary_terms_pkey ON public.academy_glossary_terms USING btree (id)"},{"name":"academy_glossary_terms_slug_key","definition":"CREATE UNIQUE INDEX academy_glossary_terms_slug_key ON public.academy_glossary_terms USING btree (slug)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_glossary_terms","permissive":"PERMISSIVE","policyname":"GodMode manages glossary","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((is_published = true) AND ((tenant_org_id IS NULL) OR is_tenant_member(tenant_org_id) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"academy_glossary_terms","permissive":"PERMISSIVE","policyname":"Published glossary visible to Academy users","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_glossary_terms_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_glossary_terms_related_course_id_fkey","definition":"FOREIGN KEY (related_course_id) REFERENCES academy_courses(id) ON DELETE SET NULL"},{"name":"academy_glossary_terms_related_module_key_fkey","definition":"FOREIGN KEY (related_module_key) REFERENCES academy_module_keys(key) ON DELETE SET NULL"},{"name":"academy_glossary_terms_slug_key","definition":"UNIQUE (slug)"}]},{"table":"academy_lesson_completions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"method","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_lesson_completions_pkey","definition":"CREATE UNIQUE INDEX academy_lesson_completions_pkey ON public.academy_lesson_completions USING btree (id)"},{"name":"academy_lesson_completions_user_id_lesson_id_method_key","definition":"CREATE UNIQUE INDEX academy_lesson_completions_user_id_lesson_id_method_key ON public.academy_lesson_completions USING btree (user_id, lesson_id, method)"},{"name":"idx_academy_lesson_completions_user","definition":"CREATE INDEX idx_academy_lesson_completions_user ON public.academy_lesson_completions USING btree (user_id, lesson_id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IS NOT NULL)","roles":["authenticated"],"tablename":"academy_lesson_completions","permissive":"RESTRICTIVE","policyname":"block null tenant completions","schemaname":"public","with_check":"(tenant_org_id IS NOT NULL)"},{"cmd":"UPDATE","qual":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_lesson_completions","permissive":"PERMISSIVE","policyname":"owners verify completions","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"academy_lesson_completions","permissive":"PERMISSIVE","policyname":"self insert completions","schemaname":"public","with_check":"(((user_id = uid()) AND is_tenant_member(tenant_org_id)) OR is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_lesson_completions","permissive":"PERMISSIVE","policyname":"self read completions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_lesson_completions_method_check","definition":"CHECK (method = ANY (ARRAY['viewed'::text, 'acknowledged'::text, 'quiz_passed'::text, 'action_completed'::text, 'roleplay_completed'::text, 'manager_verified'::text, 'manual'::text]))"},{"name":"academy_lesson_completions_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_lesson_completions_user_id_lesson_id_method_key","definition":"UNIQUE (user_id, lesson_id, method)"}]},{"table":"academy_lesson_prerequisites","schema":"public","columns":[{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"prerequisite_lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_lesson_prerequisites_pkey","definition":"CREATE UNIQUE INDEX academy_lesson_prerequisites_pkey ON public.academy_lesson_prerequisites USING btree (lesson_id, prerequisite_lesson_id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_lesson_prerequisites","permissive":"PERMISSIVE","policyname":"auth read prereqs","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_lesson_prerequisites","permissive":"PERMISSIVE","policyname":"godmode write prereqs","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_lesson_prerequisites_check","definition":"CHECK (lesson_id <> prerequisite_lesson_id)"},{"name":"academy_lesson_prerequisites_pkey","definition":"PRIMARY KEY (lesson_id, prerequisite_lesson_id)"}]},{"table":"academy_lesson_route_links","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"route","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"cta_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_lesson_route_links_pkey","definition":"CREATE UNIQUE INDEX academy_lesson_route_links_pkey ON public.academy_lesson_route_links USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_lesson_route_links","permissive":"PERMISSIVE","policyname":"auth read route links","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_lesson_route_links","permissive":"PERMISSIVE","policyname":"godmode write route links","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_lesson_route_links_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_lessons","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"unit_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"content","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lesson_type","type":"text","default":"'text'::text","identity":"","not_null":true,"generated":""},{"name":"video_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"duration_minutes","type":"integer","default":"5","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"linked_action_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"linked_route","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"content_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"learning_objective","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"role_scope","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"workflow_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sop_category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requires_acknowledgment","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"requires_quiz","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"passing_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimated_minutes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"review_status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"scenario_key","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_lessons_pkey","definition":"CREATE UNIQUE INDEX academy_lessons_pkey ON public.academy_lessons USING btree (id)"},{"name":"idx_academy_lessons_action_key","definition":"CREATE INDEX idx_academy_lessons_action_key ON public.academy_lessons USING btree (linked_action_key)"},{"name":"idx_academy_lessons_module_key","definition":"CREATE INDEX idx_academy_lessons_module_key ON public.academy_lessons USING btree (module_key)"},{"name":"idx_academy_lessons_workflow_key","definition":"CREATE INDEX idx_academy_lessons_workflow_key ON public.academy_lessons USING btree (workflow_key)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM (academy_units u\n     JOIN academy_courses c ON ((c.id = u.course_id)))\n  WHERE ((u.id = academy_lessons.unit_id) AND (is_system_admin(uid()) OR is_tenant_owner_for(uid(), c.tenant_org_id)))))","roles":["public"],"tablename":"academy_lessons","permissive":"PERMISSIVE","policyname":"Admins can manage lessons","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM (academy_units u\n     JOIN academy_courses c ON ((c.id = u.course_id)))\n  WHERE ((u.id = academy_lessons.unit_id) AND academy_course_visible(c.tenant_org_id, c.is_published))))","roles":["public"],"tablename":"academy_lessons","permissive":"PERMISSIVE","policyname":"Viewable via unit access","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_enforce_academy_lesson_grounding","definition":"CREATE TRIGGER trg_enforce_academy_lesson_grounding BEFORE INSERT OR UPDATE ON academy_lessons FOR EACH ROW EXECUTE FUNCTION enforce_academy_lesson_grounding()"},{"name":"update_academy_lessons_updated_at","definition":"CREATE TRIGGER update_academy_lessons_updated_at BEFORE UPDATE ON academy_lessons FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_lessons_lesson_type_check","definition":"CHECK (lesson_type = ANY (ARRAY['action'::text, 'sop'::text, 'concept'::text, 'quiz'::text, 'roleplay'::text, 'reference'::text, 'video'::text, 'text'::text]))"},{"name":"academy_lessons_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_lessons_review_status_check","definition":"CHECK (review_status = ANY (ARRAY['active'::text, 'review_required'::text, 'stale'::text, 'retired'::text]))"}]},{"table":"academy_manager_trainees","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"manager_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"trainee_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_manager_trainees_manager_id_trainee_id_tenant_org_i_key","definition":"CREATE UNIQUE INDEX academy_manager_trainees_manager_id_trainee_id_tenant_org_i_key ON public.academy_manager_trainees USING btree (manager_id, trainee_id, tenant_org_id)"},{"name":"academy_manager_trainees_pkey","definition":"CREATE UNIQUE INDEX academy_manager_trainees_pkey ON public.academy_manager_trainees USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"academy_manager_trainees","permissive":"PERMISSIVE","policyname":"Admins can manage assignments","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((uid() = manager_id) OR (uid() = trainee_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"academy_manager_trainees","permissive":"PERMISSIVE","policyname":"Managers can view their trainees","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_manager_trainees_manager_id_trainee_id_tenant_org_i_key","definition":"UNIQUE (manager_id, trainee_id, tenant_org_id)"},{"name":"academy_manager_trainees_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_module_keys","schema":"public","columns":[{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"verticals","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_module_keys_pkey","definition":"CREATE UNIQUE INDEX academy_module_keys_pkey ON public.academy_module_keys USING btree (key)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_module_keys","permissive":"PERMISSIVE","policyname":"auth read module_keys","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_module_keys","permissive":"PERMISSIVE","policyname":"godmode write module_keys","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_module_keys_pkey","definition":"PRIMARY KEY (key)"}]},{"table":"academy_provisioning_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"academy_track","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"details","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_provisioning_events_pkey","definition":"CREATE UNIQUE INDEX academy_provisioning_events_pkey ON public.academy_provisioning_events USING btree (id)"},{"name":"academy_provisioning_events_tenant_user_idx","definition":"CREATE INDEX academy_provisioning_events_tenant_user_idx ON public.academy_provisioning_events USING btree (tenant_id, user_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"((user_id = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = academy_provisioning_events.tenant_id) AND (membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"academy_provisioning_events","permissive":"PERMISSIVE","policyname":"academy_provisioning_events_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_provisioning_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_provisioning_events_status_check","definition":"CHECK (status = ANY (ARRAY['success'::text, 'noop'::text, 'failed'::text]))"}]},{"table":"academy_quiz_attempts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"passed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"answers","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"attempted_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_quiz_attempts_pkey","definition":"CREATE UNIQUE INDEX academy_quiz_attempts_pkey ON public.academy_quiz_attempts USING btree (id)"},{"name":"idx_academy_quiz_attempts_user_course","definition":"CREATE INDEX idx_academy_quiz_attempts_user_course ON public.academy_quiz_attempts USING btree (user_id, course_id, attempted_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"academy_quiz_attempts","permissive":"PERMISSIVE","policyname":"Users create own Academy attempts","schemaname":"public","with_check":"((user_id = uid()) AND (is_tenant_member(tenant_org_id) OR (tenant_org_id = 'platform'::text) OR is_system_admin(uid())))"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_quiz_attempts","permissive":"PERMISSIVE","policyname":"Users read own Academy attempts","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_quiz_attempts_course_id_fkey","definition":"FOREIGN KEY (course_id) REFERENCES academy_courses(id) ON DELETE CASCADE"},{"name":"academy_quiz_attempts_lesson_id_fkey","definition":"FOREIGN KEY (lesson_id) REFERENCES academy_lessons(id) ON DELETE CASCADE"},{"name":"academy_quiz_attempts_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_quiz_attempts_score_check","definition":"CHECK (score >= 0 AND score <= 100)"}]},{"table":"academy_quiz_questions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"question_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"options","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"correct_answer_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"explanation","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_quiz_questions_pkey","definition":"CREATE UNIQUE INDEX academy_quiz_questions_pkey ON public.academy_quiz_questions USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM ((academy_lessons l\n     JOIN academy_units u ON ((u.id = l.unit_id)))\n     JOIN academy_courses c ON ((c.id = u.course_id)))\n  WHERE ((l.id = academy_quiz_questions.lesson_id) AND (is_system_admin(uid()) OR is_tenant_owner_for(uid(), c.tenant_org_id)))))","roles":["public"],"tablename":"academy_quiz_questions","permissive":"PERMISSIVE","policyname":"Admins can manage quiz questions","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM ((academy_lessons l\n     JOIN academy_units u ON ((u.id = l.unit_id)))\n     JOIN academy_courses c ON ((c.id = u.course_id)))\n  WHERE ((l.id = academy_quiz_questions.lesson_id) AND academy_course_visible(c.tenant_org_id, c.is_published))))","roles":["public"],"tablename":"academy_quiz_questions","permissive":"PERMISSIVE","policyname":"Viewable via lesson access","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_quiz_questions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_roleplay_feedback","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"coach_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"trainee_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"feedback_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rating","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_roleplay_feedback_pkey","definition":"CREATE UNIQUE INDEX academy_roleplay_feedback_pkey ON public.academy_roleplay_feedback USING btree (id)"},{"name":"idx_arf_session","definition":"CREATE INDEX idx_arf_session ON public.academy_roleplay_feedback USING btree (session_id)"},{"name":"idx_arf_trainee","definition":"CREATE INDEX idx_arf_trainee ON public.academy_roleplay_feedback USING btree (trainee_id)"}],"policies":[{"cmd":"DELETE","qual":"(uid() = coach_id)","roles":["authenticated"],"tablename":"academy_roleplay_feedback","permissive":"PERMISSIVE","policyname":"Coaches delete their feedback","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"academy_roleplay_feedback","permissive":"PERMISSIVE","policyname":"Coaches insert their feedback","schemaname":"public","with_check":"(uid() = coach_id)"},{"cmd":"UPDATE","qual":"(uid() = coach_id)","roles":["authenticated"],"tablename":"academy_roleplay_feedback","permissive":"PERMISSIVE","policyname":"Coaches update their feedback","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((uid() = trainee_id) OR (uid() = coach_id))","roles":["authenticated"],"tablename":"academy_roleplay_feedback","permissive":"PERMISSIVE","policyname":"Trainee or coach views feedback","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_roleplay_feedback_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_roleplay_feedback_rating_check","definition":"CHECK (rating >= 1 AND rating <= 5)"}]},{"table":"academy_roleplay_scenarios","schema":"public","columns":[{"name":"scenario_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"icon","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scope","type":"text","default":"'global'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"required_roles","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"workflow_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"verticals","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"is_published","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_roleplay_scenarios_pkey","definition":"CREATE UNIQUE INDEX academy_roleplay_scenarios_pkey ON public.academy_roleplay_scenarios USING btree (scenario_key)"}],"policies":[{"cmd":"SELECT","qual":"((scope = 'global'::text) OR is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_roleplay_scenarios","permissive":"PERMISSIVE","policyname":"auth read global scenarios","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_system_admin(uid()) OR ((scope = 'tenant'::text) AND is_tenant_owner_for(uid(), tenant_org_id)))","roles":["authenticated"],"tablename":"academy_roleplay_scenarios","permissive":"PERMISSIVE","policyname":"owners write tenant scenarios","schemaname":"public","with_check":"(is_system_admin(uid()) OR ((scope = 'tenant'::text) AND is_tenant_owner_for(uid(), tenant_org_id)))"}],"triggers":[],"constraints":[{"name":"academy_roleplay_scenarios_pkey","definition":"PRIMARY KEY (scenario_key)"},{"name":"scenario_scope_check","definition":"CHECK (scope = ANY (ARRAY['global'::text, 'tenant'::text]))"},{"name":"tenant_scope_has_org","definition":"CHECK (scope = 'global'::text OR tenant_org_id IS NOT NULL)"}]},{"table":"academy_roleplay_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scenario_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_track","type":"text","default":"'universal'::text","identity":"","not_null":true,"generated":""},{"name":"messages","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"feedback","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_roleplay_sessions_pkey","definition":"CREATE UNIQUE INDEX academy_roleplay_sessions_pkey ON public.academy_roleplay_sessions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"can_view_tenant_member_academy(uid(), user_id)","roles":["public"],"tablename":"academy_roleplay_sessions","permissive":"PERMISSIVE","policyname":"Tenant owners view member roleplays","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"academy_roleplay_sessions","permissive":"PERMISSIVE","policyname":"Users can create sessions","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_roleplay_sessions","permissive":"PERMISSIVE","policyname":"Users can update own sessions","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_roleplay_sessions","permissive":"PERMISSIVE","policyname":"Users can view own sessions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_roleplay_sessions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_scripts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"content","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'general'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_track","type":"text","default":"'universal'::text","identity":"","not_null":true,"generated":""},{"name":"difficulty_level","type":"text","default":"'beginner'::text","identity":"","not_null":false,"generated":""},{"name":"tags","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"is_published","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"required_roles","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"workflow_key","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_scripts_pkey","definition":"CREATE UNIQUE INDEX academy_scripts_pkey ON public.academy_scripts USING btree (id)"},{"name":"idx_academy_scripts_module","definition":"CREATE INDEX idx_academy_scripts_module ON public.academy_scripts USING btree (module_key)"},{"name":"idx_academy_scripts_workflow","definition":"CREATE INDEX idx_academy_scripts_workflow ON public.academy_scripts USING btree (workflow_key)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(uid()) OR is_tenant_owner_for(uid(), tenant_org_id))","roles":["public"],"tablename":"academy_scripts","permissive":"PERMISSIVE","policyname":"Admins can manage scripts","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) AND (is_published = true))","roles":["public"],"tablename":"academy_scripts","permissive":"PERMISSIVE","policyname":"Tenant members can view scripts","schemaname":"public","with_check":null}],"triggers":[{"name":"update_academy_scripts_updated_at","definition":"CREATE TRIGGER update_academy_scripts_updated_at BEFORE UPDATE ON academy_scripts FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_scripts_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_scripts_tenant_track_check","definition":"CHECK (tenant_track = ANY (ARRAY['mitigation'::text, 'roofing'::text, 'public_adjuster'::text, 'realtor'::text, 'universal'::text]))"}]},{"table":"academy_tenant_course_overrides","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"override_course_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_hidden","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"is_required","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_tenant_course_overrid_tenant_org_id_source_course_i_key","definition":"CREATE UNIQUE INDEX academy_tenant_course_overrid_tenant_org_id_source_course_i_key ON public.academy_tenant_course_overrides USING btree (tenant_org_id, source_course_id)"},{"name":"academy_tenant_course_overrides_pkey","definition":"CREATE UNIQUE INDEX academy_tenant_course_overrides_pkey ON public.academy_tenant_course_overrides USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_tenant_course_overrides","permissive":"PERMISSIVE","policyname":"Owners manage Academy course overrides","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_tenant_course_overrides","permissive":"PERMISSIVE","policyname":"Tenant members read Academy course overrides","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_tenant_course_overrid_tenant_org_id_source_course_i_key","definition":"UNIQUE (tenant_org_id, source_course_id)"},{"name":"academy_tenant_course_overrides_override_course_id_fkey","definition":"FOREIGN KEY (override_course_id) REFERENCES academy_courses(id) ON DELETE SET NULL"},{"name":"academy_tenant_course_overrides_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_tenant_course_overrides_source_course_id_fkey","definition":"FOREIGN KEY (source_course_id) REFERENCES academy_courses(id) ON DELETE CASCADE"}]},{"table":"academy_tenant_modules","schema":"public","columns":[{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"module_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"enabled_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"enabled_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_tenant_modules_pkey","definition":"CREATE UNIQUE INDEX academy_tenant_modules_pkey ON public.academy_tenant_modules USING btree (tenant_org_id, module_key)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IS NOT NULL)","roles":["authenticated"],"tablename":"academy_tenant_modules","permissive":"RESTRICTIVE","policyname":"block null tenant modules","schemaname":"public","with_check":"(tenant_org_id IS NOT NULL)"},{"cmd":"ALL","qual":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_tenant_modules","permissive":"PERMISSIVE","policyname":"owners write modules","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_tenant_modules","permissive":"PERMISSIVE","policyname":"tenant members read modules","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_tenant_modules_pkey","definition":"PRIMARY KEY (tenant_org_id, module_key)"}]},{"table":"academy_trainee_progress","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lesson_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_trainee_progress_pkey","definition":"CREATE UNIQUE INDEX academy_trainee_progress_pkey ON public.academy_trainee_progress USING btree (id)"},{"name":"academy_trainee_progress_user_id_lesson_id_key","definition":"CREATE UNIQUE INDEX academy_trainee_progress_user_id_lesson_id_key ON public.academy_trainee_progress USING btree (user_id, lesson_id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"academy_trainee_progress","permissive":"PERMISSIVE","policyname":"Admins can view all progress","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"can_view_tenant_member_academy(uid(), user_id)","roles":["public"],"tablename":"academy_trainee_progress","permissive":"PERMISSIVE","policyname":"Tenant owners view member progress","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"academy_trainee_progress","permissive":"PERMISSIVE","policyname":"Users can manage own progress","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_trainee_progress","permissive":"PERMISSIVE","policyname":"Users can update own progress","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_trainee_progress","permissive":"PERMISSIVE","policyname":"Users can view own progress","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_sync_enrollment_progress","definition":"CREATE TRIGGER trg_sync_enrollment_progress AFTER INSERT OR DELETE OR UPDATE ON academy_trainee_progress FOR EACH ROW EXECUTE FUNCTION tg_sync_enrollment_progress()"},{"name":"update_academy_trainee_progress_updated_at","definition":"CREATE TRIGGER update_academy_trainee_progress_updated_at BEFORE UPDATE ON academy_trainee_progress FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_trainee_progress_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_trainee_progress_status_check","definition":"CHECK (status = ANY (ARRAY['not_started'::text, 'in_progress'::text, 'completed'::text]))"},{"name":"academy_trainee_progress_user_id_lesson_id_key","definition":"UNIQUE (user_id, lesson_id)"}]},{"table":"academy_units","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_units_pkey","definition":"CREATE UNIQUE INDEX academy_units_pkey ON public.academy_units USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM academy_courses c\n  WHERE ((c.id = academy_units.course_id) AND (is_system_admin(uid()) OR is_tenant_owner_for(uid(), c.tenant_org_id)))))","roles":["public"],"tablename":"academy_units","permissive":"PERMISSIVE","policyname":"Admins can manage units","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM academy_courses c\n  WHERE ((c.id = academy_units.course_id) AND academy_course_visible(c.tenant_org_id, c.is_published))))","roles":["public"],"tablename":"academy_units","permissive":"PERMISSIVE","policyname":"Viewable via course access","schemaname":"public","with_check":null}],"triggers":[{"name":"update_academy_units_updated_at","definition":"CREATE TRIGGER update_academy_units_updated_at BEFORE UPDATE ON academy_units FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_units_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"academy_user_assignments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"course_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'assigned'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_user_assignments_pkey","definition":"CREATE UNIQUE INDEX academy_user_assignments_pkey ON public.academy_user_assignments USING btree (id)"},{"name":"academy_user_assignments_tenant_org_id_user_id_course_id_key","definition":"CREATE UNIQUE INDEX academy_user_assignments_tenant_org_id_user_id_course_id_key ON public.academy_user_assignments USING btree (tenant_org_id, user_id, course_id)"},{"name":"idx_academy_user_assignments_user","definition":"CREATE INDEX idx_academy_user_assignments_user ON public.academy_user_assignments USING btree (user_id, status)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IS NOT NULL)","roles":["authenticated"],"tablename":"academy_user_assignments","permissive":"RESTRICTIVE","policyname":"block null tenant assignments","schemaname":"public","with_check":"(tenant_org_id IS NOT NULL)"},{"cmd":"ALL","qual":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_user_assignments","permissive":"PERMISSIVE","policyname":"owners write assignments","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_tenant_owner_for(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"academy_user_assignments","permissive":"PERMISSIVE","policyname":"self read assignments","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_user_assignments_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_user_assignments_tenant_org_id_user_id_course_id_key","definition":"UNIQUE (tenant_org_id, user_id, course_id)"}]},{"table":"academy_user_badges","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"badge_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"earned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_user_badges_pkey","definition":"CREATE UNIQUE INDEX academy_user_badges_pkey ON public.academy_user_badges USING btree (id)"},{"name":"academy_user_badges_user_id_badge_id_key","definition":"CREATE UNIQUE INDEX academy_user_badges_user_id_badge_id_key ON public.academy_user_badges USING btree (user_id, badge_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"academy_user_badges","permissive":"PERMISSIVE","policyname":"System can award badges","schemaname":"public","with_check":"((uid() = user_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"can_view_tenant_member_academy(uid(), user_id)","roles":["public"],"tablename":"academy_user_badges","permissive":"PERMISSIVE","policyname":"Tenant owners view member badges","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_user_badges","permissive":"PERMISSIVE","policyname":"Users can view own badges","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"academy_user_badges_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_user_badges_user_id_badge_id_key","definition":"UNIQUE (user_id, badge_id)"}]},{"table":"academy_user_points","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"total_points","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"streak_days","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_activity_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"academy_user_points_pkey","definition":"CREATE UNIQUE INDEX academy_user_points_pkey ON public.academy_user_points USING btree (id)"},{"name":"academy_user_points_user_id_tenant_org_id_key","definition":"CREATE UNIQUE INDEX academy_user_points_user_id_tenant_org_id_key ON public.academy_user_points USING btree (user_id, tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["public"],"tablename":"academy_user_points","permissive":"PERMISSIVE","policyname":"Tenant members can view leaderboard","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"academy_user_points","permissive":"PERMISSIVE","policyname":"Users can manage own points","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["public"],"tablename":"academy_user_points","permissive":"PERMISSIVE","policyname":"Users can update own points","schemaname":"public","with_check":null}],"triggers":[{"name":"update_academy_user_points_updated_at","definition":"CREATE TRIGGER update_academy_user_points_updated_at BEFORE UPDATE ON academy_user_points FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"academy_user_points_pkey","definition":"PRIMARY KEY (id)"},{"name":"academy_user_points_user_id_tenant_org_id_key","definition":"UNIQUE (user_id, tenant_org_id)"}]},{"table":"academy_workflow_keys","schema":"public","columns":[{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"module_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"academy_workflow_keys_pkey","definition":"CREATE UNIQUE INDEX academy_workflow_keys_pkey ON public.academy_workflow_keys USING btree (key)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"academy_workflow_keys","permissive":"PERMISSIVE","policyname":"auth read workflow_keys","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"academy_workflow_keys","permissive":"PERMISSIVE","policyname":"godmode write workflow_keys","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"academy_workflow_keys_pkey","definition":"PRIMARY KEY (key)"}]},{"table":"acceptance_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_version","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_agreement_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"session_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"acceptance_events_pkey","definition":"CREATE UNIQUE INDEX acceptance_events_pkey ON public.acceptance_events USING btree (id)"},{"name":"idx_acceptance_events_created_at","definition":"CREATE INDEX idx_acceptance_events_created_at ON public.acceptance_events USING btree (created_at DESC)"},{"name":"idx_acceptance_events_event_type","definition":"CREATE INDEX idx_acceptance_events_event_type ON public.acceptance_events USING btree (event_type)"},{"name":"idx_acceptance_events_template","definition":"CREATE INDEX idx_acceptance_events_template ON public.acceptance_events USING btree (template_id)"},{"name":"idx_acceptance_events_user_tenant","definition":"CREATE INDEX idx_acceptance_events_user_tenant ON public.acceptance_events USING btree (user_id, tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = acceptance_events.tenant_id) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text]))))))","roles":["authenticated"],"tablename":"acceptance_events","permissive":"PERMISSIVE","policyname":"Admins can view tenant acceptance events","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"acceptance_events","permissive":"PERMISSIVE","policyname":"Authenticated users can insert their own acceptance events","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"acceptance_events","permissive":"PERMISSIVE","policyname":"Users can view their own acceptance events","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_acceptance_events_no_delete","definition":"CREATE TRIGGER trg_acceptance_events_no_delete BEFORE DELETE ON acceptance_events FOR EACH ROW EXECUTE FUNCTION block_mutation_append_only()"},{"name":"trg_acceptance_events_no_update","definition":"CREATE TRIGGER trg_acceptance_events_no_update BEFORE UPDATE ON acceptance_events FOR EACH ROW EXECUTE FUNCTION block_mutation_append_only()"}],"constraints":[{"name":"acceptance_events_event_type_check","definition":"CHECK (event_type = ANY (ARRAY['gate_shown'::text, 'document_viewed'::text, 'document_downloaded'::text, 'document_emailed'::text, 'declined'::text, 'signed'::text, 'reaccepted_after_bump'::text, 'superseded'::text]))"},{"name":"acceptance_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"achievements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"achievement_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"icon","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"unlock_criteria","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"points","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"rarity","type":"text","default":"'common'::text","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"achievements_achievement_key_key","definition":"CREATE UNIQUE INDEX achievements_achievement_key_key ON public.achievements USING btree (achievement_key)"},{"name":"achievements_pkey","definition":"CREATE UNIQUE INDEX achievements_pkey ON public.achievements USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["public"],"tablename":"achievements","permissive":"PERMISSIVE","policyname":"All users view achievements","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"achievements_achievement_key_key","definition":"UNIQUE (achievement_key)"},{"name":"achievements_pkey","definition":"PRIMARY KEY (id)"},{"name":"achievements_rarity_check","definition":"CHECK (rarity = ANY (ARRAY['common'::text, 'rare'::text, 'epic'::text, 'legendary'::text]))"}]},{"table":"acting_pm_grants","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"granted_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"granted_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"acting_pm_grants_pkey","definition":"CREATE UNIQUE INDEX acting_pm_grants_pkey ON public.acting_pm_grants USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(is_manager_or_higher_strict(uid(), tenant_id) OR (user_id = uid()) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"acting_pm_grants","permissive":"PERMISSIVE","policyname":"acting_pm_grants_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_manager_or_higher_strict(uid(), tenant_id) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"acting_pm_grants","permissive":"PERMISSIVE","policyname":"acting_pm_grants_write","schemaname":"public","with_check":"(is_manager_or_higher_strict(uid(), tenant_id) OR is_platform_admin(uid()))"}],"triggers":[],"constraints":[{"name":"acting_pm_grants_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"action_errors","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"route","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_component","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"button_label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"domain","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"action_errors_pkey","definition":"CREATE UNIQUE INDEX action_errors_pkey ON public.action_errors USING btree (id)"},{"name":"idx_action_errors_action_id","definition":"CREATE INDEX idx_action_errors_action_id ON public.action_errors USING btree (action_id)"},{"name":"idx_action_errors_created_at","definition":"CREATE INDEX idx_action_errors_created_at ON public.action_errors USING btree (created_at DESC)"},{"name":"idx_action_errors_domain","definition":"CREATE INDEX idx_action_errors_domain ON public.action_errors USING btree (domain)"},{"name":"idx_action_errors_resolved","definition":"CREATE INDEX idx_action_errors_resolved ON public.action_errors USING btree (resolved_at) WHERE (resolved_at IS NULL)"},{"name":"idx_action_errors_user_id","definition":"CREATE INDEX idx_action_errors_user_id ON public.action_errors USING btree (user_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"action_errors","permissive":"PERMISSIVE","policyname":"Users can log their own action errors","schemaname":"public","with_check":"((uid() = user_id) OR (user_id IS NULL))"},{"cmd":"UPDATE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"action_errors","permissive":"PERMISSIVE","policyname":"platform_admin_update_action_errors","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"action_errors","permissive":"PERMISSIVE","policyname":"platform_admin_view_action_errors","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"action_errors_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"active_call_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":"'twilio'::text","identity":"","not_null":true,"generated":""},{"name":"parent_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"homeowner_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'initiated'::text","identity":"","not_null":true,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"ended_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"force_ended_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"force_ended_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"force_ended_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_armed_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_armed_slot","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_armed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"terminal_outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"terminal_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"auto_advanced","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"drop_and_go_state","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"active_call_sessions_pkey","definition":"CREATE UNIQUE INDEX active_call_sessions_pkey ON public.active_call_sessions USING btree (id)"},{"name":"idx_acs_rep_active","definition":"CREATE INDEX idx_acs_rep_active ON public.active_call_sessions USING btree (rep_id, status)"},{"name":"idx_acs_tenant","definition":"CREATE INDEX idx_acs_tenant ON public.active_call_sessions USING btree (tenant_org_id)"},{"name":"idx_acs_terminal","definition":"CREATE INDEX idx_acs_terminal ON public.active_call_sessions USING btree (rep_id, terminal_at DESC) WHERE (terminal_outcome IS NOT NULL)"},{"name":"idx_acs_vm_armed","definition":"CREATE INDEX idx_acs_vm_armed ON public.active_call_sessions USING btree (voicemail_armed_template_id) WHERE (voicemail_armed_template_id IS NOT NULL)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"active_call_sessions","permissive":"PERMISSIVE","policyname":"acs_insert_self","schemaname":"public","with_check":"(((rep_id = uid()) AND is_tenant_member(tenant_org_id)) OR is_system_admin())"},{"cmd":"SELECT","qual":"((rep_id = uid()) OR (is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"active_call_sessions","permissive":"PERMISSIVE","policyname":"acs_select_tenant","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((rep_id = uid()) OR (is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"active_call_sessions","permissive":"PERMISSIVE","policyname":"acs_update_self","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"active_call_sessions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"activity_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"activity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"activity_log_pkey","definition":"CREATE UNIQUE INDEX activity_log_pkey ON public.activity_log USING btree (id)"},{"name":"idx_activity_log_contact_id","definition":"CREATE INDEX idx_activity_log_contact_id ON public.activity_log USING btree (contact_id)"},{"name":"idx_activity_log_created_at","definition":"CREATE INDEX idx_activity_log_created_at ON public.activity_log USING btree (created_at DESC)"},{"name":"idx_activity_log_tenant_id","definition":"CREATE INDEX idx_activity_log_tenant_id ON public.activity_log USING btree (tenant_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"activity_log","permissive":"PERMISSIVE","policyname":"Users create activities","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = activity_log.tenant_id))))","roles":["public"],"tablename":"activity_log","permissive":"PERMISSIVE","policyname":"Users view tenant activities","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"activity_log_pkey","definition":"PRIMARY KEY (id)"},{"name":"activity_log_verified_external_actor_check","definition":"CHECK (user_id IS NOT NULL OR activity_type = 'portal_message'::text AND (metadata ->> 'source'::text) = 'customer_portal'::text)"}]},{"table":"activity_timeline","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"activity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"related_entity_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_entity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"importance","type":"text","default":"'normal'::text","identity":"","not_null":false,"generated":""},{"name":"is_system_generated","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"activity_timeline_pkey","definition":"CREATE UNIQUE INDEX activity_timeline_pkey ON public.activity_timeline USING btree (id)"},{"name":"idx_activity_timeline_contact","definition":"CREATE INDEX idx_activity_timeline_contact ON public.activity_timeline USING btree (contact_id)"},{"name":"idx_activity_timeline_tenant_created","definition":"CREATE INDEX idx_activity_timeline_tenant_created ON public.activity_timeline USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"activity_timeline","permissive":"PERMISSIVE","policyname":"Tenant isolation for activity_timeline","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"activity_timeline_activity_type_check","definition":"CHECK (activity_type = ANY (ARRAY['call'::text, 'email'::text, 'sms'::text, 'note'::text, 'task'::text, 'meeting'::text, 'status_change'::text, 'stage_change'::text, 'assignment'::text, 'document'::text, 'photo'::text, 'automation'::text, 'score_change'::text, 'merge'::text, 'import'::text, 'export'::text, 'field_update'::text]))"},{"name":"activity_timeline_importance_check","definition":"CHECK (importance = ANY (ARRAY['low'::text, 'normal'::text, 'high'::text, 'critical'::text]))"},{"name":"activity_timeline_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"admin_saved_queries","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sql_query","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_shared","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"admin_saved_queries_created_by_idx","definition":"CREATE INDEX admin_saved_queries_created_by_idx ON public.admin_saved_queries USING btree (created_by, created_at DESC)"},{"name":"admin_saved_queries_pkey","definition":"CREATE UNIQUE INDEX admin_saved_queries_pkey ON public.admin_saved_queries USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"admin_saved_queries","permissive":"PERMISSIVE","policyname":"Admins create saved queries","schemaname":"public","with_check":"((uid() = created_by) AND is_platform_admin(uid()))"},{"cmd":"SELECT","qual":"is_platform_admin(uid())","roles":["authenticated"],"tablename":"admin_saved_queries","permissive":"PERMISSIVE","policyname":"Admins read saved queries","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((uid() = created_by) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"admin_saved_queries","permissive":"PERMISSIVE","policyname":"Owners or admins delete saved queries","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((uid() = created_by) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"admin_saved_queries","permissive":"PERMISSIVE","policyname":"Owners or admins update saved queries","schemaname":"public","with_check":"((uid() = created_by) OR is_platform_admin(uid()))"}],"triggers":[{"name":"admin_saved_queries_set_updated_at","definition":"CREATE TRIGGER admin_saved_queries_set_updated_at BEFORE UPDATE ON admin_saved_queries FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"admin_saved_queries_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"aerial_measurement_orders","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"order_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_order_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lat","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"lng","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"product_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"report_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"report_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ordered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"aerial_measurement_orders_pkey","definition":"CREATE UNIQUE INDEX aerial_measurement_orders_pkey ON public.aerial_measurement_orders USING btree (id)"},{"name":"idx_aerial_orders_contact","definition":"CREATE INDEX idx_aerial_orders_contact ON public.aerial_measurement_orders USING btree (contact_id)"},{"name":"idx_aerial_orders_estimate","definition":"CREATE INDEX idx_aerial_orders_estimate ON public.aerial_measurement_orders USING btree (estimate_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"aerial_measurement_orders","permissive":"PERMISSIVE","policyname":"Users create tenant aerial orders","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"aerial_measurement_orders","permissive":"PERMISSIVE","policyname":"Users update tenant aerial orders","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"aerial_measurement_orders","permissive":"PERMISSIVE","policyname":"Users view tenant aerial orders","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"aerial_measurement_orders_pkey","definition":"PRIMARY KEY (id)"},{"name":"aerial_measurement_orders_provider_check","definition":"CHECK (provider = ANY (ARRAY['eagleview'::text, 'gaf'::text, 'roofsnap'::text, 'other'::text]))"},{"name":"aerial_measurement_orders_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'ordered'::text, 'processing'::text, 'completed'::text, 'failed'::text, 'cancelled'::text]))"}]},{"table":"agent_presence","schema":"public","columns":[{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'offline'::text","identity":"","not_null":true,"generated":""},{"name":"current_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_seen_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"agent_presence_pkey","definition":"CREATE UNIQUE INDEX agent_presence_pkey ON public.agent_presence USING btree (user_id)"},{"name":"idx_agent_presence_tenant","definition":"CREATE INDEX idx_agent_presence_tenant ON public.agent_presence USING btree (tenant_id, status)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"agent_presence","permissive":"PERMISSIVE","policyname":"Reps insert own presence","schemaname":"public","with_check":"((user_id = uid()) AND is_tenant_member(uid(), tenant_id))"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"agent_presence","permissive":"PERMISSIVE","policyname":"Reps update own presence","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"agent_presence","permissive":"PERMISSIVE","policyname":"Tenant members view presence","schemaname":"public","with_check":null}],"triggers":[{"name":"update_agent_presence_updated_at","definition":"CREATE TRIGGER update_agent_presence_updated_at BEFORE UPDATE ON agent_presence FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"agent_presence_pkey","definition":"PRIMARY KEY (user_id)"},{"name":"agent_presence_status_check","definition":"CHECK (status = ANY (ARRAY['available'::text, 'on_call'::text, 'wrap_up'::text, 'break'::text, 'offline'::text]))"}]},{"table":"agreement_requirements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"min_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"is_required","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"display_order","type":"integer","default":"100","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"agreement_requirements_pkey","definition":"CREATE UNIQUE INDEX agreement_requirements_pkey ON public.agreement_requirements USING btree (id)"},{"name":"agreement_requirements_tenant_type_role_template_type_tenan_key","definition":"CREATE UNIQUE INDEX agreement_requirements_tenant_type_role_template_type_tenan_key ON public.agreement_requirements USING btree (tenant_type, role, template_type, tenant_id)"},{"name":"idx_agreement_requirements_lookup","definition":"CREATE INDEX idx_agreement_requirements_lookup ON public.agreement_requirements USING btree (tenant_type, role, is_required)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"agreement_requirements","permissive":"PERMISSIVE","policyname":"Authenticated users can read applicable requirements","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"agreement_requirements","permissive":"PERMISSIVE","policyname":"System admins manage all requirements","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = (agreement_requirements.tenant_id)::text) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text]))))))","roles":["authenticated"],"tablename":"agreement_requirements","permissive":"PERMISSIVE","policyname":"Tenant owners manage their tenant requirements","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = (agreement_requirements.tenant_id)::text) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text]))))))"}],"triggers":[{"name":"trg_agreement_requirements_updated_at","definition":"CREATE TRIGGER trg_agreement_requirements_updated_at BEFORE UPDATE ON agreement_requirements FOR EACH ROW EXECUTE FUNCTION tg_set_updated_at()"}],"constraints":[{"name":"agreement_requirements_pkey","definition":"PRIMARY KEY (id)"},{"name":"agreement_requirements_tenant_type_role_template_type_tenan_key","definition":"UNIQUE (tenant_type, role, template_type, tenant_id)"}]},{"table":"agreement_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"template_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"html_content","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"change_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_rep_visible","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"effective_date","type":"date","default":"CURRENT_DATE","identity":"","not_null":true,"generated":""},{"name":"requires_reacceptance_on_bump","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"applies_to_tenant_types","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"applies_to_roles","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"is_universal","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"short_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"display_order","type":"integer","default":"100","identity":"","not_null":true,"generated":""},{"name":"derived_from_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"adopted_admin_version","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"agreement_templates_pkey","definition":"CREATE UNIQUE INDEX agreement_templates_pkey ON public.agreement_templates USING btree (id)"},{"name":"idx_agreement_templates_active","definition":"CREATE INDEX idx_agreement_templates_active ON public.agreement_templates USING btree (is_active)"},{"name":"idx_agreement_templates_derived","definition":"CREATE INDEX idx_agreement_templates_derived ON public.agreement_templates USING btree (derived_from_template_id)"},{"name":"idx_agreement_templates_type","definition":"CREATE INDEX idx_agreement_templates_type ON public.agreement_templates USING btree (template_type)"},{"name":"uq_template_type_version","definition":"CREATE UNIQUE INDEX uq_template_type_version ON public.agreement_templates USING btree (template_type, version)"}],"policies":[{"cmd":"SELECT","qual":"((uid() IS NOT NULL) AND (is_active = true))","roles":["public"],"tablename":"agreement_templates","permissive":"PERMISSIVE","policyname":"Authenticated users can read active templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"agreement_templates","permissive":"PERMISSIVE","policyname":"System admins manage all agreement templates","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = (agreement_templates.tenant_id)::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role]))))))","roles":["authenticated"],"tablename":"agreement_templates","permissive":"PERMISSIVE","policyname":"Tenant admins manage their agreement templates","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = (agreement_templates.tenant_id)::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role]))))))"}],"triggers":[],"constraints":[{"name":"agreement_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"uq_template_type_version","definition":"UNIQUE (template_type, version)"}]},{"table":"ai_conversations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"surface","type":"text","default":"'global'::text","identity":"","not_null":true,"generated":""},{"name":"context_lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"context_property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"context_workflow_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_archived","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"last_message_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ai_conversations_lead_idx","definition":"CREATE INDEX ai_conversations_lead_idx ON public.ai_conversations USING btree (tenant_org_id, context_lead_id) WHERE (context_lead_id IS NOT NULL)"},{"name":"ai_conversations_pkey","definition":"CREATE UNIQUE INDEX ai_conversations_pkey ON public.ai_conversations USING btree (id)"},{"name":"ai_conversations_property_idx","definition":"CREATE INDEX ai_conversations_property_idx ON public.ai_conversations USING btree (tenant_org_id, context_property_id) WHERE (context_property_id IS NOT NULL)"},{"name":"ai_conversations_tenant_user_idx","definition":"CREATE INDEX ai_conversations_tenant_user_idx ON public.ai_conversations USING btree (tenant_org_id, user_id, last_message_at DESC)"}],"policies":[{"cmd":"DELETE","qual":"((user_id = uid()) OR ai_is_tenant_admin(tenant_org_id))","roles":["authenticated"],"tablename":"ai_conversations","permissive":"PERMISSIVE","policyname":"ai_conv_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"ai_conversations","permissive":"PERMISSIVE","policyname":"ai_conv_insert","schemaname":"public","with_check":"((user_id = uid()) AND ai_user_in_tenant(tenant_org_id))"},{"cmd":"SELECT","qual":"(ai_user_in_tenant(tenant_org_id) AND ((user_id = uid()) OR ai_is_tenant_admin(tenant_org_id)))","roles":["authenticated"],"tablename":"ai_conversations","permissive":"PERMISSIVE","policyname":"ai_conv_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((user_id = uid()) OR ai_is_tenant_admin(tenant_org_id))","roles":["authenticated"],"tablename":"ai_conversations","permissive":"PERMISSIVE","policyname":"ai_conv_update","schemaname":"public","with_check":null}],"triggers":[{"name":"ai_conv_touch","definition":"CREATE TRIGGER ai_conv_touch BEFORE UPDATE ON ai_conversations FOR EACH ROW EXECUTE FUNCTION ai_touch_updated_at()"}],"constraints":[{"name":"ai_conversations_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ai_failures","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"conversation_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"failure_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"http_status","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"tool_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"redacted_payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ai_failures_pkey","definition":"CREATE UNIQUE INDEX ai_failures_pkey ON public.ai_failures USING btree (id)"},{"name":"ai_failures_tenant_idx","definition":"CREATE INDEX ai_failures_tenant_idx ON public.ai_failures USING btree (tenant_org_id, created_at DESC)"},{"name":"ai_failures_type_idx","definition":"CREATE INDEX ai_failures_type_idx ON public.ai_failures USING btree (failure_type, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"((tenant_org_id IS NOT NULL) AND ai_is_tenant_admin(tenant_org_id))","roles":["authenticated"],"tablename":"ai_failures","permissive":"PERMISSIVE","policyname":"ai_fail_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"ai_failures_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ai_messages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"conversation_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"content","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"structured","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"tool_calls","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"tool_call_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"model","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"prompt_tokens","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"completion_tokens","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"total_tokens","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"latency_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"warnings","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ai_messages_conv_idx","definition":"CREATE INDEX ai_messages_conv_idx ON public.ai_messages USING btree (conversation_id, created_at)"},{"name":"ai_messages_pkey","definition":"CREATE UNIQUE INDEX ai_messages_pkey ON public.ai_messages USING btree (id)"},{"name":"ai_messages_tenant_idx","definition":"CREATE INDEX ai_messages_tenant_idx ON public.ai_messages USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"ai_messages","permissive":"PERMISSIVE","policyname":"ai_msg_insert","schemaname":"public","with_check":"((user_id = uid()) AND ai_user_in_tenant(tenant_org_id))"},{"cmd":"SELECT","qual":"(ai_user_in_tenant(tenant_org_id) AND ((user_id = uid()) OR ai_is_tenant_admin(tenant_org_id)))","roles":["authenticated"],"tablename":"ai_messages","permissive":"PERMISSIVE","policyname":"ai_msg_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"ai_messages_pkey","definition":"PRIMARY KEY (id)"},{"name":"ai_messages_role_check","definition":"CHECK (role = ANY (ARRAY['system'::text, 'user'::text, 'assistant'::text, 'tool'::text]))"}]},{"table":"ai_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"conversation_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"surface","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"prompt_category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"model","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"request_mode","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"prompt_tokens","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"completion_tokens","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"total_tokens","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"latency_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"tools_called","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"success","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"http_status","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"fallback_used","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ai_requests_pkey","definition":"CREATE UNIQUE INDEX ai_requests_pkey ON public.ai_requests USING btree (id)"},{"name":"ai_requests_tenant_idx","definition":"CREATE INDEX ai_requests_tenant_idx ON public.ai_requests USING btree (tenant_org_id, created_at DESC)"},{"name":"ai_requests_user_idx","definition":"CREATE INDEX ai_requests_user_idx ON public.ai_requests USING btree (user_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(ai_is_tenant_admin(tenant_org_id) OR (user_id = uid()))","roles":["authenticated"],"tablename":"ai_requests","permissive":"PERMISSIVE","policyname":"ai_req_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"ai_requests_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ai_tool_calls","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"conversation_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"message_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tool_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tool_call_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_write","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'proposed'::text","identity":"","not_null":true,"generated":""},{"name":"input","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"output","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requires_confirmation","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"confirmed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"confirmed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ai_tool_calls_conv_idx","definition":"CREATE INDEX ai_tool_calls_conv_idx ON public.ai_tool_calls USING btree (conversation_id, created_at)"},{"name":"ai_tool_calls_pkey","definition":"CREATE UNIQUE INDEX ai_tool_calls_pkey ON public.ai_tool_calls USING btree (id)"},{"name":"ai_tool_calls_status_idx","definition":"CREATE INDEX ai_tool_calls_status_idx ON public.ai_tool_calls USING btree (tenant_org_id, status, created_at DESC)"},{"name":"ai_tool_calls_tenant_idx","definition":"CREATE INDEX ai_tool_calls_tenant_idx ON public.ai_tool_calls USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"ai_tool_calls","permissive":"PERMISSIVE","policyname":"ai_tool_insert","schemaname":"public","with_check":"((user_id = uid()) AND ai_user_in_tenant(tenant_org_id))"},{"cmd":"SELECT","qual":"(ai_user_in_tenant(tenant_org_id) AND ((user_id = uid()) OR ai_is_tenant_admin(tenant_org_id)))","roles":["authenticated"],"tablename":"ai_tool_calls","permissive":"PERMISSIVE","policyname":"ai_tool_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((user_id = uid()) OR ai_is_tenant_admin(tenant_org_id))","roles":["authenticated"],"tablename":"ai_tool_calls","permissive":"PERMISSIVE","policyname":"ai_tool_update","schemaname":"public","with_check":null}],"triggers":[{"name":"ai_tool_touch","definition":"CREATE TRIGGER ai_tool_touch BEFORE UPDATE ON ai_tool_calls FOR EACH ROW EXECUTE FUNCTION ai_touch_updated_at()"}],"constraints":[{"name":"ai_tool_calls_pkey","definition":"PRIMARY KEY (id)"},{"name":"ai_tool_calls_status_check","definition":"CHECK (status = ANY (ARRAY['proposed'::text, 'confirmed'::text, 'completed'::text, 'failed'::text, 'cancelled'::text]))"}]},{"table":"analytics_metrics","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metric_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metric_value","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"metric_type","type":"text","default":"'gauge'::text","identity":"","not_null":false,"generated":""},{"name":"dimensions","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"analytics_metrics_pkey","definition":"CREATE UNIQUE INDEX analytics_metrics_pkey ON public.analytics_metrics USING btree (id)"},{"name":"idx_analytics_metric_name","definition":"CREATE INDEX idx_analytics_metric_name ON public.analytics_metrics USING btree (metric_name)"},{"name":"idx_analytics_tenant_id","definition":"CREATE INDEX idx_analytics_tenant_id ON public.analytics_metrics USING btree (tenant_id)"},{"name":"idx_analytics_timestamp","definition":"CREATE INDEX idx_analytics_timestamp ON public.analytics_metrics USING btree (\"timestamp\" DESC)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"analytics_metrics","permissive":"PERMISSIVE","policyname":"platform_admin_view_analytics","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"analytics_metrics","permissive":"PERMISSIVE","policyname":"users_insert_tenant_metrics","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND ((utm.tenant_id)::text = (analytics_metrics.tenant_id)::text) AND (utm.status = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"analytics_metrics_metric_type_check","definition":"CHECK (metric_type = ANY (ARRAY['counter'::text, 'gauge'::text, 'histogram'::text]))"},{"name":"analytics_metrics_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"analytics_snapshots","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"snapshot_type","type":"character varying(50)","default":null,"identity":"","not_null":true,"generated":""},{"name":"snapshot_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"metrics","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"dimensions","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"analytics_snapshots_pkey","definition":"CREATE UNIQUE INDEX analytics_snapshots_pkey ON public.analytics_snapshots USING btree (id)"},{"name":"idx_analytics_snapshots_date","definition":"CREATE INDEX idx_analytics_snapshots_date ON public.analytics_snapshots USING btree (snapshot_date)"},{"name":"idx_analytics_snapshots_tenant","definition":"CREATE INDEX idx_analytics_snapshots_tenant ON public.analytics_snapshots USING btree (tenant_id)"},{"name":"unique_tenant_snapshot","definition":"CREATE UNIQUE INDEX unique_tenant_snapshot ON public.analytics_snapshots USING btree (tenant_id, snapshot_type, snapshot_date)"}],"policies":[{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"analytics_snapshots","permissive":"PERMISSIVE","policyname":"Users can view own tenant snapshots","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"analytics_snapshots_pkey","definition":"PRIMARY KEY (id)"},{"name":"unique_tenant_snapshot","definition":"UNIQUE (tenant_id, snapshot_type, snapshot_date)"}]},{"table":"appointment_outcome_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"booking_rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_starts_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"prev_outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_outcome","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"changed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"appointment_outcome_audit_pkey","definition":"CREATE UNIQUE INDEX appointment_outcome_audit_pkey ON public.appointment_outcome_audit USING btree (id)"},{"name":"idx_aoa_contact","definition":"CREATE INDEX idx_aoa_contact ON public.appointment_outcome_audit USING btree (contact_id, changed_at DESC)"},{"name":"idx_aoa_tenant_rep","definition":"CREATE INDEX idx_aoa_tenant_rep ON public.appointment_outcome_audit USING btree (tenant_org_id, booking_rep_id, changed_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN tenants t ON ((t.id = ur.tenant_id)))\n  WHERE ((ur.user_id = uid()) AND ((t.id)::text = appointment_outcome_audit.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'Manager'::app_role, 'Tenant Owner'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"appointment_outcome_audit","permissive":"PERMISSIVE","policyname":"manager_plus_read_outcome_audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"appointment_outcome_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"appointment_settings","schema":"public","columns":[{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"company_calendar_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"invite_emails","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"send_customer_sms","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"send_customer_email","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"send_24h_reminder","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"send_1h_reminder","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"notify_owner_emails","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"send_rep_booking_notification","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"send_agreement_signed_followup","type":"boolean","default":"true","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"appointment_settings_pkey","definition":"CREATE UNIQUE INDEX appointment_settings_pkey ON public.appointment_settings USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = appointment_settings.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'Manager'::app_role, 'Tenant Owner'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"appointment_settings","permissive":"PERMISSIVE","policyname":"manager_plus_read_appt_settings","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = appointment_settings.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'Tenant Owner'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"appointment_settings","permissive":"PERMISSIVE","policyname":"owner_admin_write_appt_settings","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = appointment_settings.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'Tenant Owner'::app_role, 'GodMode'::app_role]))))))"}],"triggers":[{"name":"trg_touch_appt_settings","definition":"CREATE TRIGGER trg_touch_appt_settings BEFORE UPDATE ON appointment_settings FOR EACH ROW EXECUTE FUNCTION touch_appointment_settings_updated_at()"}],"constraints":[{"name":"appointment_settings_pkey","definition":"PRIMARY KEY (tenant_org_id)"}]},{"table":"auto_unlock_upload_tickets","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":"'d60e3c27-73ed-4a5f-a49b-c37636455daf'::uuid","identity":"","not_null":true,"generated":""},{"name":"bucket_id","type":"text","default":"'tenant-d60e3c27-73ed-4a5f-a49b-c37636455daf'::text","identity":"","not_null":true,"generated":""},{"name":"object_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"proof_kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"declared_filename","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"declared_mime","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"declared_size","type":"bigint","default":null,"identity":"","not_null":true,"generated":""},{"name":"ip_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"consumed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"auto_unlock_upload_tickets_expiry_idx","definition":"CREATE INDEX auto_unlock_upload_tickets_expiry_idx ON public.auto_unlock_upload_tickets USING btree (expires_at) WHERE (consumed_at IS NULL)"},{"name":"auto_unlock_upload_tickets_ip_created_idx","definition":"CREATE INDEX auto_unlock_upload_tickets_ip_created_idx ON public.auto_unlock_upload_tickets USING btree (ip_hash, created_at DESC)"},{"name":"auto_unlock_upload_tickets_object_path_key","definition":"CREATE UNIQUE INDEX auto_unlock_upload_tickets_object_path_key ON public.auto_unlock_upload_tickets USING btree (object_path)"},{"name":"auto_unlock_upload_tickets_pkey","definition":"CREATE UNIQUE INDEX auto_unlock_upload_tickets_pkey ON public.auto_unlock_upload_tickets USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"auto_unlock_upload_ticket_bucket","definition":"CHECK (bucket_id = 'tenant-d60e3c27-73ed-4a5f-a49b-c37636455daf'::text)"},{"name":"auto_unlock_upload_ticket_path","definition":"CHECK (object_path ~ '^public-intake/(identity|authority)/[0-9a-f-]+\\.(jpg|png|webp|heic|heif|pdf)$'::text)"},{"name":"auto_unlock_upload_ticket_tenant","definition":"CHECK (tenant_id = 'd60e3c27-73ed-4a5f-a49b-c37636455daf'::uuid)"},{"name":"auto_unlock_upload_tickets_declared_mime_check","definition":"CHECK (declared_mime = ANY (ARRAY['image/jpeg'::text, 'image/png'::text, 'image/webp'::text, 'image/heic'::text, 'image/heif'::text, 'application/pdf'::text]))"},{"name":"auto_unlock_upload_tickets_declared_size_check","definition":"CHECK (declared_size > 0 AND declared_size <= 10485760)"},{"name":"auto_unlock_upload_tickets_ip_hash_check","definition":"CHECK (ip_hash ~ '^[0-9a-f]{64}$'::text)"},{"name":"auto_unlock_upload_tickets_object_path_key","definition":"UNIQUE (object_path)"},{"name":"auto_unlock_upload_tickets_pkey","definition":"PRIMARY KEY (id)"},{"name":"auto_unlock_upload_tickets_proof_kind_check","definition":"CHECK (proof_kind = ANY (ARRAY['identity'::text, 'authority'::text]))"}]},{"table":"automation_rule_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"template_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"vertical","type":"text","default":"'universal'::text","identity":"","not_null":true,"generated":""},{"name":"trigger_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"conditions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"actions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"icon","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_for_verticals","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"automation_rule_templates_pkey","definition":"CREATE UNIQUE INDEX automation_rule_templates_pkey ON public.automation_rule_templates USING btree (id)"},{"name":"automation_rule_templates_template_key_key","definition":"CREATE UNIQUE INDEX automation_rule_templates_template_key_key ON public.automation_rule_templates USING btree (template_key)"},{"name":"idx_automation_templates_category","definition":"CREATE INDEX idx_automation_templates_category ON public.automation_rule_templates USING btree (category)"},{"name":"idx_automation_templates_verticals","definition":"CREATE INDEX idx_automation_templates_verticals ON public.automation_rule_templates USING gin (recommended_for_verticals)"}],"policies":[{"cmd":"SELECT","qual":"(is_active = true)","roles":["authenticated"],"tablename":"automation_rule_templates","permissive":"PERMISSIVE","policyname":"Anyone authenticated can read active templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"automation_rule_templates","permissive":"PERMISSIVE","policyname":"System admins manage templates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"automation_rule_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"automation_rule_templates_template_key_key","definition":"UNIQUE (template_key)"}]},{"table":"automation_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"trigger_event","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"conditions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"actions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"execution_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"automation_rules_pkey","definition":"CREATE UNIQUE INDEX automation_rules_pkey ON public.automation_rules USING btree (id)"},{"name":"idx_automation_rules_active","definition":"CREATE INDEX idx_automation_rules_active ON public.automation_rules USING btree (tenant_id) WHERE (is_active = true)"},{"name":"idx_automation_rules_tenant","definition":"CREATE INDEX idx_automation_rules_tenant ON public.automation_rules USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = ur.user_id) AND (m.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = automation_rules.tenant_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"automation_rules","permissive":"PERMISSIVE","policyname":"Admins can manage automation rules","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = ur.user_id) AND (m.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = automation_rules.tenant_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = automation_rules.tenant_id)))))","roles":["authenticated"],"tablename":"automation_rules","permissive":"PERMISSIVE","policyname":"Tenant members can view automation rules","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"automation_rules_created_by_fkey","definition":"FOREIGN KEY (created_by) REFERENCES users(id)"},{"name":"automation_rules_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"automation_run_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rule_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rule_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"engine","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_kind","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"entity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'success'::text","identity":"","not_null":true,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"dry_run","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"actions_executed","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"automation_run_log_pkey","definition":"CREATE UNIQUE INDEX automation_run_log_pkey ON public.automation_run_log USING btree (id)"},{"name":"idx_automation_run_log_rule","definition":"CREATE INDEX idx_automation_run_log_rule ON public.automation_run_log USING btree (rule_id, created_at DESC)"},{"name":"idx_automation_run_log_status","definition":"CREATE INDEX idx_automation_run_log_status ON public.automation_run_log USING btree (status)"},{"name":"idx_automation_run_log_tenant","definition":"CREATE INDEX idx_automation_run_log_tenant ON public.automation_run_log USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"true","roles":["service_role"],"tablename":"automation_run_log","permissive":"PERMISSIVE","policyname":"Service role manages automation runs","schemaname":"public","with_check":"true"},{"cmd":"SELECT","qual":"((tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid()))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"automation_run_log","permissive":"PERMISSIVE","policyname":"Tenant members read their automation runs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"automation_run_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"billing_comps","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"scope","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"granted_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"billing_comps_pkey","definition":"CREATE UNIQUE INDEX billing_comps_pkey ON public.billing_comps USING btree (id)"},{"name":"billing_comps_tenant_unique","definition":"CREATE UNIQUE INDEX billing_comps_tenant_unique ON public.billing_comps USING btree (tenant_id) WHERE (scope = 'tenant'::text)"},{"name":"billing_comps_user_unique","definition":"CREATE UNIQUE INDEX billing_comps_user_unique ON public.billing_comps USING btree (user_id) WHERE (scope = 'user'::text)"}],"policies":[{"cmd":"ALL","qual":"is_platform_admin(uid())","roles":["authenticated"],"tablename":"billing_comps","permissive":"PERMISSIVE","policyname":"Admins manage billing comps","schemaname":"public","with_check":"is_platform_admin(uid())"},{"cmd":"SELECT","qual":"(((scope = 'user'::text) AND (user_id = uid())) OR ((scope = 'tenant'::text) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = billing_comps.tenant_id))))))","roles":["authenticated"],"tablename":"billing_comps","permissive":"PERMISSIVE","policyname":"Users view own applicable comps","schemaname":"public","with_check":null}],"triggers":[{"name":"update_billing_comps_updated_at","definition":"CREATE TRIGGER update_billing_comps_updated_at BEFORE UPDATE ON billing_comps FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"billing_comps_pkey","definition":"PRIMARY KEY (id)"},{"name":"billing_comps_scope_check","definition":"CHECK (scope = ANY (ARRAY['tenant'::text, 'user'::text]))"},{"name":"billing_comps_scope_target","definition":"CHECK (scope = 'tenant'::text AND tenant_id IS NOT NULL AND user_id IS NULL OR scope = 'user'::text AND user_id IS NOT NULL AND tenant_id IS NULL)"}]},{"table":"brevard_permit_confidence_feedback","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"jurisdiction_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_parcel","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"detected_jurisdiction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"detected_confidence","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"feedback_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"corrected_jurisdiction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"submitted_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"brevard_permit_confidence_feedback_pkey","definition":"CREATE UNIQUE INDEX brevard_permit_confidence_feedback_pkey ON public.brevard_permit_confidence_feedback USING btree (id)"},{"name":"idx_brevard_feedback_created","definition":"CREATE INDEX idx_brevard_feedback_created ON public.brevard_permit_confidence_feedback USING btree (created_at DESC)"},{"name":"idx_brevard_feedback_jur","definition":"CREATE INDEX idx_brevard_feedback_jur ON public.brevard_permit_confidence_feedback USING btree (jurisdiction_id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"brevard_permit_confidence_feedback","permissive":"PERMISSIVE","policyname":"brevard_feedback_admin_read","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"brevard_permit_confidence_feedback","permissive":"PERMISSIVE","policyname":"brevard_feedback_authenticated_insert","schemaname":"public","with_check":"true"}],"triggers":[],"constraints":[{"name":"brevard_permit_confidence_feedback_feedback_type_check","definition":"CHECK (feedback_type = ANY (ARRAY['CONFIRMED_CORRECT'::text, 'WRONG_JURISDICTION'::text, 'NEEDS_REVIEW'::text, 'MANUAL_PERMIT_FOUND'::text, 'MANUAL_NO_PERMIT_FOUND'::text, 'PORTAL_LINK_BAD'::text, 'SOURCE_UNRELIABLE'::text]))"},{"name":"brevard_permit_confidence_feedback_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"brevard_permit_jurisdictions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"normalized_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"aliases","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"county","type":"text","default":"'Brevard'::text","identity":"","not_null":true,"generated":""},{"name":"state","type":"text","default":"'FL'::text","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_type","type":"text","default":"'city'::text","identity":"","not_null":true,"generated":""},{"name":"coverage_status","type":"brevard_permit_coverage_status","default":"'PORTAL_ASSISTED'::brevard_permit_coverage_status","identity":"","not_null":true,"generated":""},{"name":"platform","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"official_building_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_search_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_application_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"public_records_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"supports_address_search","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"supports_parcel_search","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"supports_owner_search","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"supports_permit_number_search","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"requires_login","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"captcha_detected","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"js_heavy","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"automation_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_search_instructions","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"confidence_score","type":"integer","default":"50","identity":"","not_null":true,"generated":""},{"name":"last_verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_successful_search_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_failure_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"brevard_permit_jurisdictions_normalized_name_key","definition":"CREATE UNIQUE INDEX brevard_permit_jurisdictions_normalized_name_key ON public.brevard_permit_jurisdictions USING btree (normalized_name)"},{"name":"brevard_permit_jurisdictions_pkey","definition":"CREATE UNIQUE INDEX brevard_permit_jurisdictions_pkey ON public.brevard_permit_jurisdictions USING btree (id)"},{"name":"idx_brevard_jur_normalized","definition":"CREATE INDEX idx_brevard_jur_normalized ON public.brevard_permit_jurisdictions USING btree (normalized_name)"},{"name":"idx_brevard_jur_status","definition":"CREATE INDEX idx_brevard_jur_status ON public.brevard_permit_jurisdictions USING btree (coverage_status)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"brevard_permit_jurisdictions","permissive":"PERMISSIVE","policyname":"brevard_jur_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"brevard_permit_jurisdictions","permissive":"PERMISSIVE","policyname":"brevard_jur_admin_insert","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"UPDATE","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"brevard_permit_jurisdictions","permissive":"PERMISSIVE","policyname":"brevard_jur_admin_update","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"brevard_permit_jurisdictions","permissive":"PERMISSIVE","policyname":"brevard_jur_read_authenticated","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_brevard_jur_updated_at","definition":"CREATE TRIGGER trg_brevard_jur_updated_at BEFORE UPDATE ON brevard_permit_jurisdictions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"brevard_permit_jurisdictions_normalized_name_key","definition":"UNIQUE (normalized_name)"},{"name":"brevard_permit_jurisdictions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"brevard_permit_manual_results","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"jurisdiction_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"issued_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"finaled_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"contractor_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"entered_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"brevard_permit_manual_results_pkey","definition":"CREATE UNIQUE INDEX brevard_permit_manual_results_pkey ON public.brevard_permit_manual_results USING btree (id)"},{"name":"idx_brevard_manual_property","definition":"CREATE INDEX idx_brevard_manual_property ON public.brevard_permit_manual_results USING btree (property_id)"},{"name":"idx_brevard_manual_tenant","definition":"CREATE INDEX idx_brevard_manual_tenant ON public.brevard_permit_manual_results USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"brevard_permit_manual_results","permissive":"PERMISSIVE","policyname":"brevard_manual_delete_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"brevard_permit_manual_results","permissive":"PERMISSIVE","policyname":"brevard_manual_insert_tenant","schemaname":"public","with_check":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), tenant_org_id)))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), tenant_org_id)))","roles":["authenticated"],"tablename":"brevard_permit_manual_results","permissive":"PERMISSIVE","policyname":"brevard_manual_read_tenant","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), tenant_org_id)))","roles":["authenticated"],"tablename":"brevard_permit_manual_results","permissive":"PERMISSIVE","policyname":"brevard_manual_update_tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_brevard_manual_updated_at","definition":"CREATE TRIGGER trg_brevard_manual_updated_at BEFORE UPDATE ON brevard_permit_manual_results FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"brevard_permit_manual_results_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"brevard_permit_search_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"jurisdiction_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_parcel","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_owner","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_permit_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"coverage_status","type":"brevard_permit_coverage_status","default":null,"identity":"","not_null":false,"generated":""},{"name":"search_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"result_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"result_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_response","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"brevard_permit_search_logs_pkey","definition":"CREATE UNIQUE INDEX brevard_permit_search_logs_pkey ON public.brevard_permit_search_logs USING btree (id)"},{"name":"idx_brevard_logs_created","definition":"CREATE INDEX idx_brevard_logs_created ON public.brevard_permit_search_logs USING btree (created_at DESC)"},{"name":"idx_brevard_logs_jur","definition":"CREATE INDEX idx_brevard_logs_jur ON public.brevard_permit_search_logs USING btree (jurisdiction_id)"},{"name":"idx_brevard_logs_property","definition":"CREATE INDEX idx_brevard_logs_property ON public.brevard_permit_search_logs USING btree (property_id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"brevard_permit_search_logs","permissive":"PERMISSIVE","policyname":"brevard_logs_admin_read","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"brevard_permit_search_logs","permissive":"PERMISSIVE","policyname":"brevard_logs_authenticated_insert","schemaname":"public","with_check":"true"}],"triggers":[],"constraints":[{"name":"brevard_permit_search_logs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"business_attention_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"opportunity_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"priority","type":"text","default":"'normal'::text","identity":"","not_null":true,"generated":""},{"name":"state","type":"text","default":"'open'::text","identity":"","not_null":true,"generated":""},{"name":"deterministic_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"action_route","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"business_attention_items_pkey","definition":"CREATE UNIQUE INDEX business_attention_items_pkey ON public.business_attention_items USING btree (id)"},{"name":"business_attention_items_tenant_id_deterministic_key_key","definition":"CREATE UNIQUE INDEX business_attention_items_tenant_id_deterministic_key_key ON public.business_attention_items USING btree (tenant_id, deterministic_key)"},{"name":"business_attention_open_due_idx","definition":"CREATE INDEX business_attention_open_due_idx ON public.business_attention_items USING btree (tenant_id, state, due_at) WHERE (state = ANY (ARRAY['open'::text, 'acknowledged'::text]))"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"business_attention_items","permissive":"PERMISSIVE","policyname":"business_attention_items_select","schemaname":"public","with_check":null}],"triggers":[{"name":"business_attention_items_touch_updated_at","definition":"CREATE TRIGGER business_attention_items_touch_updated_at BEFORE UPDATE ON business_attention_items FOR EACH ROW EXECUTE FUNCTION business_engine_touch_updated_at()"}],"constraints":[{"name":"business_attention_items_kind_check","definition":"CHECK (kind = ANY (ARRAY['opportunity_response_due'::text, 'proposal_followup_due'::text, 'deposit_due'::text, 'scheduling_needed'::text, 'balance_due'::text]))"},{"name":"business_attention_items_opportunity_id_fkey","definition":"FOREIGN KEY (opportunity_id) REFERENCES business_opportunities(id) ON DELETE CASCADE"},{"name":"business_attention_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"business_attention_items_priority_check","definition":"CHECK (priority = ANY (ARRAY['low'::text, 'normal'::text, 'high'::text, 'urgent'::text]))"},{"name":"business_attention_items_state_check","definition":"CHECK (state = ANY (ARRAY['open'::text, 'acknowledged'::text, 'resolved'::text, 'dismissed'::text]))"},{"name":"business_attention_items_tenant_id_deterministic_key_key","definition":"UNIQUE (tenant_id, deterministic_key)"},{"name":"business_attention_items_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"business_hours_overrides","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"routing_profile_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"override_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"closed","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"open_time","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"close_time","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"business_hours_overrides_pkey","definition":"CREATE UNIQUE INDEX business_hours_overrides_pkey ON public.business_hours_overrides USING btree (id)"},{"name":"uq_bh_override_profile_date","definition":"CREATE UNIQUE INDEX uq_bh_override_profile_date ON public.business_hours_overrides USING btree (routing_profile_id, override_date)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"business_hours_overrides","permissive":"PERMISSIVE","policyname":"business_hours_overrides_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"business_hours_overrides","permissive":"PERMISSIVE","policyname":"business_hours_overrides_write_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"}],"triggers":[],"constraints":[{"name":"business_hours_overrides_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"business_opportunities","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_module","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""},{"name":"source_entity_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_entity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"dedupe_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"confidence_score","type":"numeric(5,4)","default":null,"identity":"","not_null":false,"generated":""},{"name":"lifecycle_state","type":"text","default":"'captured'::text","identity":"","not_null":true,"generated":""},{"name":"proposal_state","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"payment_state","type":"text","default":"'not_required'::text","identity":"","not_null":true,"generated":""},{"name":"fulfillment_state","type":"text","default":"'not_scheduled'::text","identity":"","not_null":true,"generated":""},{"name":"estimated_value","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"quoted_amount","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"deposit_amount","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"balance_amount","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"invoice_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"calendar_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"response_due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"proposal_followup_due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deposit_due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"fulfillment_due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"balance_due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"proposal_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"accepted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deposit_paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"fulfillment_completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"lost_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"cancelled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"business_opportunities_contact_idx","definition":"CREATE INDEX business_opportunities_contact_idx ON public.business_opportunities USING btree (tenant_id, contact_id) WHERE (contact_id IS NOT NULL)"},{"name":"business_opportunities_pkey","definition":"CREATE UNIQUE INDEX business_opportunities_pkey ON public.business_opportunities USING btree (id)"},{"name":"business_opportunities_tenant_commercial_idx","definition":"CREATE INDEX business_opportunities_tenant_commercial_idx ON public.business_opportunities USING btree (tenant_id, proposal_state, payment_state, fulfillment_state)"},{"name":"business_opportunities_tenant_id_dedupe_key_key","definition":"CREATE UNIQUE INDEX business_opportunities_tenant_id_dedupe_key_key ON public.business_opportunities USING btree (tenant_id, dedupe_key)"},{"name":"business_opportunities_tenant_lifecycle_idx","definition":"CREATE INDEX business_opportunities_tenant_lifecycle_idx ON public.business_opportunities USING btree (tenant_id, lifecycle_state, updated_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"business_opportunities","permissive":"PERMISSIVE","policyname":"business_opportunities_select","schemaname":"public","with_check":null}],"triggers":[{"name":"business_opportunities_refresh_attention","definition":"CREATE TRIGGER business_opportunities_refresh_attention AFTER INSERT OR UPDATE OF lifecycle_state, proposal_state, payment_state, fulfillment_state, response_due_at, proposal_followup_due_at, deposit_due_at, fulfillment_due_at, balance_due_at ON business_opportunities FOR EACH ROW EXECUTE FUNCTION business_engine_attention_trigger()"},{"name":"business_opportunities_touch_updated_at","definition":"CREATE TRIGGER business_opportunities_touch_updated_at BEFORE UPDATE ON business_opportunities FOR EACH ROW EXECUTE FUNCTION business_engine_touch_updated_at()"}],"constraints":[{"name":"business_opportunities_balance_amount_check","definition":"CHECK (balance_amount IS NULL OR balance_amount >= 0::numeric)"},{"name":"business_opportunities_calendar_event_id_fkey","definition":"FOREIGN KEY (calendar_event_id) REFERENCES user_calendar_events(id) ON DELETE SET NULL"},{"name":"business_opportunities_confidence_score_check","definition":"CHECK (confidence_score IS NULL OR confidence_score >= 0::numeric AND confidence_score <= 1::numeric)"},{"name":"business_opportunities_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"business_opportunities_deposit_amount_check","definition":"CHECK (deposit_amount IS NULL OR deposit_amount >= 0::numeric)"},{"name":"business_opportunities_estimated_value_check","definition":"CHECK (estimated_value IS NULL OR estimated_value >= 0::numeric)"},{"name":"business_opportunities_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"business_opportunities_fulfillment_state_check","definition":"CHECK (fulfillment_state = ANY (ARRAY['not_scheduled'::text, 'scheduled'::text, 'in_progress'::text, 'completed'::text, 'cancelled'::text]))"},{"name":"business_opportunities_invoice_id_fkey","definition":"FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL"},{"name":"business_opportunities_lifecycle_state_check","definition":"CHECK (lifecycle_state = ANY (ARRAY['captured'::text, 'qualified'::text, 'won'::text, 'lost'::text, 'cancelled'::text]))"},{"name":"business_opportunities_payment_state_check","definition":"CHECK (payment_state = ANY (ARRAY['not_required'::text, 'deposit_due'::text, 'deposit_overdue'::text, 'deposit_paid'::text, 'balance_due'::text, 'balance_overdue'::text, 'paid'::text, 'refunded'::text, 'void'::text]))"},{"name":"business_opportunities_pkey","definition":"PRIMARY KEY (id)"},{"name":"business_opportunities_proposal_state_check","definition":"CHECK (proposal_state = ANY (ARRAY['not_started'::text, 'draft'::text, 'sent'::text, 'accepted'::text, 'declined'::text, 'void'::text]))"},{"name":"business_opportunities_quoted_amount_check","definition":"CHECK (quoted_amount IS NULL OR quoted_amount >= 0::numeric)"},{"name":"business_opportunities_source_event_id_fkey","definition":"FOREIGN KEY (source_event_id) REFERENCES intelligence_events(id) ON DELETE SET NULL"},{"name":"business_opportunities_tenant_id_dedupe_key_key","definition":"UNIQUE (tenant_id, dedupe_key)"},{"name":"business_opportunities_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"business_opportunity_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"opportunity_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"dimension","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"business_opportunity_events_history_idx","definition":"CREATE INDEX business_opportunity_events_history_idx ON public.business_opportunity_events USING btree (opportunity_id, created_at DESC)"},{"name":"business_opportunity_events_pkey","definition":"CREATE UNIQUE INDEX business_opportunity_events_pkey ON public.business_opportunity_events USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"business_opportunity_events","permissive":"PERMISSIVE","policyname":"business_opportunity_events_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"business_opportunity_events_dimension_check","definition":"CHECK (dimension = ANY (ARRAY['materialization'::text, 'lifecycle'::text, 'proposal'::text, 'payment'::text, 'fulfillment'::text, 'terms'::text]))"},{"name":"business_opportunity_events_opportunity_id_fkey","definition":"FOREIGN KEY (opportunity_id) REFERENCES business_opportunities(id) ON DELETE CASCADE"},{"name":"business_opportunity_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"business_opportunity_events_source_event_id_fkey","definition":"FOREIGN KEY (source_event_id) REFERENCES intelligence_events(id) ON DELETE SET NULL"},{"name":"business_opportunity_events_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"business_workflow_policies","schema":"public","columns":[{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"auto_create_from_intelligence","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"opportunity_auto_create_min_confidence","type":"numeric(5,4)","default":"0.8000","identity":"","not_null":true,"generated":""},{"name":"response_due_minutes","type":"integer","default":"60","identity":"","not_null":true,"generated":""},{"name":"proposal_followup_hours","type":"integer","default":"48","identity":"","not_null":true,"generated":""},{"name":"deposit_due_hours","type":"integer","default":"72","identity":"","not_null":true,"generated":""},{"name":"balance_due_hours","type":"integer","default":"24","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"business_workflow_policies_pkey","definition":"CREATE UNIQUE INDEX business_workflow_policies_pkey ON public.business_workflow_policies USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"ai_is_tenant_admin(tenant_id)","roles":["authenticated"],"tablename":"business_workflow_policies","permissive":"PERMISSIVE","policyname":"business_workflow_policies_admin_manage","schemaname":"public","with_check":"ai_is_tenant_admin(tenant_id)"},{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"business_workflow_policies","permissive":"PERMISSIVE","policyname":"business_workflow_policies_select","schemaname":"public","with_check":null}],"triggers":[{"name":"business_workflow_policies_touch_updated_at","definition":"CREATE TRIGGER business_workflow_policies_touch_updated_at BEFORE UPDATE ON business_workflow_policies FOR EACH ROW EXECUTE FUNCTION business_engine_touch_updated_at()"}],"constraints":[{"name":"business_workflow_policies_balance_due_hours_check","definition":"CHECK (balance_due_hours >= 1 AND balance_due_hours <= 2160)"},{"name":"business_workflow_policies_deposit_due_hours_check","definition":"CHECK (deposit_due_hours >= 1 AND deposit_due_hours <= 2160)"},{"name":"business_workflow_policies_opportunity_auto_create_min_co_check","definition":"CHECK (opportunity_auto_create_min_confidence >= 0::numeric AND opportunity_auto_create_min_confidence <= 1::numeric)"},{"name":"business_workflow_policies_pkey","definition":"PRIMARY KEY (tenant_id)"},{"name":"business_workflow_policies_proposal_followup_hours_check","definition":"CHECK (proposal_followup_hours >= 1 AND proposal_followup_hours <= 2160)"},{"name":"business_workflow_policies_response_due_minutes_check","definition":"CHECK (response_due_minutes >= 1 AND response_due_minutes <= 10080)"},{"name":"business_workflow_policies_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"cached_parcel_roof_ages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"parcel_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"year_built","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_age_score","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"viewport_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"fetched_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sqft_heated","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"assessed_value","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"land_use","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sale_price","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"sale_date","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_permit_year","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"year_built_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parcel_geometry","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"geometry_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"geometry_fetched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"cached_parcel_roof_ages_pkey","definition":"CREATE UNIQUE INDEX cached_parcel_roof_ages_pkey ON public.cached_parcel_roof_ages USING btree (id)"},{"name":"idx_cached_parcel_roof_ages_fetched_at","definition":"CREATE INDEX idx_cached_parcel_roof_ages_fetched_at ON public.cached_parcel_roof_ages USING btree (fetched_at DESC)"},{"name":"idx_cached_parcels_coords","definition":"CREATE INDEX idx_cached_parcels_coords ON public.cached_parcel_roof_ages USING btree (lat, lng)"},{"name":"idx_cached_parcels_parcel_id","definition":"CREATE UNIQUE INDEX idx_cached_parcels_parcel_id ON public.cached_parcel_roof_ages USING btree (parcel_id)"},{"name":"idx_cached_parcels_viewport","definition":"CREATE INDEX idx_cached_parcels_viewport ON public.cached_parcel_roof_ages USING btree (viewport_key)"}],"policies":[{"cmd":"SELECT","qual":"(( SELECT uid() AS uid) IS NOT NULL)","roles":["authenticated"],"tablename":"cached_parcel_roof_ages","permissive":"PERMISSIVE","policyname":"Authenticated read cached parcels","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"true","roles":["service_role"],"tablename":"cached_parcel_roof_ages","permissive":"PERMISSIVE","policyname":"Service role manages cached parcels","schemaname":"public","with_check":"true"},{"cmd":"UPDATE","qual":"( SELECT has_any_active_tenant_membership(uid()) AS has_any_active_tenant_membership)","roles":["authenticated"],"tablename":"cached_parcel_roof_ages","permissive":"PERMISSIVE","policyname":"Tenant members update cached parcels","schemaname":"public","with_check":"( SELECT has_any_active_tenant_membership(uid()) AS has_any_active_tenant_membership)"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"cached_parcel_roof_ages","permissive":"PERMISSIVE","policyname":"Tenant members upsert cached parcels","schemaname":"public","with_check":"( SELECT has_any_active_tenant_membership(uid()) AS has_any_active_tenant_membership)"}],"triggers":[],"constraints":[{"name":"cached_parcel_roof_ages_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"cafe_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"kind","type":"text","default":"'promotion'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"starts_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"ends_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_campaigns_pkey","definition":"CREATE UNIQUE INDEX cafe_campaigns_pkey ON public.cafe_campaigns USING btree (id)"},{"name":"cafe_campaigns_tenant_created_idx","definition":"CREATE INDEX cafe_campaigns_tenant_created_idx ON public.cafe_campaigns USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_campaigns.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_campaigns","permissive":"PERMISSIVE","policyname":"cafe_campaigns_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_campaigns.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"cafe_campaigns_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_campaigns_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'scheduled'::text, 'active'::text, 'paused'::text, 'completed'::text]))"},{"name":"cafe_campaigns_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"cafe_loyalty_members","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"points_balance","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"tier","type":"text","default":"'member'::text","identity":"","not_null":true,"generated":""},{"name":"visits","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_loyalty_members_pkey","definition":"CREATE UNIQUE INDEX cafe_loyalty_members_pkey ON public.cafe_loyalty_members USING btree (id)"},{"name":"cafe_loyalty_members_tenant_updated_idx","definition":"CREATE INDEX cafe_loyalty_members_tenant_updated_idx ON public.cafe_loyalty_members USING btree (tenant_org_id, updated_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_loyalty_members.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_loyalty_members","permissive":"PERMISSIVE","policyname":"cafe_loyalty_members_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_loyalty_members.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"cafe_loyalty_members_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_loyalty_members_points_balance_check","definition":"CHECK (points_balance >= 0)"},{"name":"cafe_loyalty_members_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"cafe_loyalty_members_visits_check","definition":"CHECK (visits >= 0)"}]},{"table":"cafe_menu_item_media","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"menu_item_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"asset_role","type":"text","default":"'primary'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'needed'::text","identity":"","not_null":true,"generated":""},{"name":"image_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"alt_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"creative_brief","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"generation_prompt","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"source_references","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_primary","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_menu_item_media_one_primary_idx","definition":"CREATE UNIQUE INDEX cafe_menu_item_media_one_primary_idx ON public.cafe_menu_item_media USING btree (menu_item_id) WHERE is_primary"},{"name":"cafe_menu_item_media_pkey","definition":"CREATE UNIQUE INDEX cafe_menu_item_media_pkey ON public.cafe_menu_item_media USING btree (id)"},{"name":"cafe_menu_item_media_tenant_item_idx","definition":"CREATE INDEX cafe_menu_item_media_tenant_item_idx ON public.cafe_menu_item_media USING btree (tenant_org_id, menu_item_id, sort_order)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_menu_item_media.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_menu_item_media","permissive":"PERMISSIVE","policyname":"cafe_menu_item_media_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_menu_item_media.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"}],"triggers":[{"name":"cafe_menu_item_media_touch_updated_at","definition":"CREATE TRIGGER cafe_menu_item_media_touch_updated_at BEFORE UPDATE ON cafe_menu_item_media FOR EACH ROW EXECUTE FUNCTION touch_cafe_menu_item_media_updated_at()"}],"constraints":[{"name":"cafe_menu_item_media_asset_role_check","definition":"CHECK (asset_role = ANY (ARRAY['primary'::text, 'alternate'::text, 'reference'::text]))"},{"name":"cafe_menu_item_media_menu_item_id_fkey","definition":"FOREIGN KEY (menu_item_id) REFERENCES cafe_menu_items(id) ON DELETE CASCADE"},{"name":"cafe_menu_item_media_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_menu_item_media_status_check","definition":"CHECK (status = ANY (ARRAY['needed'::text, 'brief_ready'::text, 'generating'::text, 'ready'::text, 'rejected'::text]))"},{"name":"cafe_menu_item_media_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"cafe_menu_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"external_item_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"menu_section","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"price","type":"numeric(10,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"available","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"stock_quantity","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"low_stock_alert","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"modifiers","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"tags","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"image_url","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"cafe_menu_items_pkey","definition":"CREATE UNIQUE INDEX cafe_menu_items_pkey ON public.cafe_menu_items USING btree (id)"},{"name":"cafe_menu_items_tenant_available_sort_idx","definition":"CREATE INDEX cafe_menu_items_tenant_available_sort_idx ON public.cafe_menu_items USING btree (tenant_org_id, available, sort_order)"},{"name":"cafe_menu_items_tenant_org_id_external_item_id_key","definition":"CREATE UNIQUE INDEX cafe_menu_items_tenant_org_id_external_item_id_key ON public.cafe_menu_items USING btree (tenant_org_id, external_item_id)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_menu_items.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_menu_items","permissive":"PERMISSIVE","policyname":"cafe_menu_items_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_menu_items.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"},{"cmd":"SELECT","qual":"(available AND (EXISTS ( SELECT 1\n   FROM cafe_public_settings public_settings\n  WHERE ((public_settings.tenant_org_id = cafe_menu_items.tenant_org_id) AND (public_settings.slug = 'thirsty-panda'::text)))))","roles":["anon","authenticated"],"tablename":"cafe_menu_items","permissive":"PERMISSIVE","policyname":"cafe_menu_items_public_read","schemaname":"public","with_check":null}],"triggers":[{"name":"cafe_menu_items_media_stub_after_insert","definition":"CREATE TRIGGER cafe_menu_items_media_stub_after_insert AFTER INSERT ON cafe_menu_items FOR EACH ROW EXECUTE FUNCTION ensure_cafe_menu_item_media_stub()"}],"constraints":[{"name":"cafe_menu_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_menu_items_price_check","definition":"CHECK (price >= 0::numeric)"},{"name":"cafe_menu_items_tenant_org_id_external_item_id_key","definition":"UNIQUE (tenant_org_id, external_item_id)"},{"name":"cafe_menu_items_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"cafe_order_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"order_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"menu_item_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"item_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"quantity","type":"numeric(10,3)","default":"1","identity":"","not_null":true,"generated":""},{"name":"unit_price","type":"numeric(10,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"selected_modifiers","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_order_items_pkey","definition":"CREATE UNIQUE INDEX cafe_order_items_pkey ON public.cafe_order_items USING btree (id)"},{"name":"cafe_order_items_tenant_order_sort_idx","definition":"CREATE INDEX cafe_order_items_tenant_order_sort_idx ON public.cafe_order_items USING btree (tenant_org_id, order_id, sort_order)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_order_items.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_order_items","permissive":"PERMISSIVE","policyname":"cafe_order_items_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_order_items.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"cafe_order_items_menu_item_id_fkey","definition":"FOREIGN KEY (menu_item_id) REFERENCES cafe_menu_items(id) ON DELETE SET NULL"},{"name":"cafe_order_items_order_id_fkey","definition":"FOREIGN KEY (order_id) REFERENCES cafe_orders(id) ON DELETE CASCADE"},{"name":"cafe_order_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_order_items_quantity_check","definition":"CHECK (quantity > 0::numeric)"},{"name":"cafe_order_items_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"cafe_order_items_unit_price_check","definition":"CHECK (unit_price >= 0::numeric)"}]},{"table":"cafe_orders","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"order_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'clover'::text","identity":"","not_null":true,"generated":""},{"name":"order_type","type":"text","default":"'pickup'::text","identity":"","not_null":true,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'accepted'::text","identity":"","not_null":true,"generated":""},{"name":"subtotal","type":"numeric(10,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"tax","type":"numeric(10,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"total","type":"numeric(10,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_orders_pkey","definition":"CREATE UNIQUE INDEX cafe_orders_pkey ON public.cafe_orders USING btree (id)"},{"name":"cafe_orders_tenant_created_idx","definition":"CREATE INDEX cafe_orders_tenant_created_idx ON public.cafe_orders USING btree (tenant_org_id, created_at DESC)"},{"name":"cafe_orders_tenant_org_id_order_number_key","definition":"CREATE UNIQUE INDEX cafe_orders_tenant_org_id_order_number_key ON public.cafe_orders USING btree (tenant_org_id, order_number)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_orders.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_orders","permissive":"PERMISSIVE","policyname":"cafe_orders_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_orders.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"cafe_orders_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_orders_status_check","definition":"CHECK (status = ANY (ARRAY['accepted'::text, 'preparing'::text, 'ready'::text, 'completed'::text, 'cancelled'::text]))"},{"name":"cafe_orders_subtotal_check","definition":"CHECK (subtotal >= 0::numeric)"},{"name":"cafe_orders_tax_check","definition":"CHECK (tax >= 0::numeric)"},{"name":"cafe_orders_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"cafe_orders_tenant_org_id_order_number_key","definition":"UNIQUE (tenant_org_id, order_number)"},{"name":"cafe_orders_total_check","definition":"CHECK (total >= 0::numeric)"}]},{"table":"cafe_public_settings","schema":"public","columns":[{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"logo_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"hero_video_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"clover_status","type":"text","default":"'setup_required'::text","identity":"","not_null":true,"generated":""},{"name":"clover_checkout_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_public_settings_pkey","definition":"CREATE UNIQUE INDEX cafe_public_settings_pkey ON public.cafe_public_settings USING btree (tenant_org_id)"},{"name":"cafe_public_settings_slug_key","definition":"CREATE UNIQUE INDEX cafe_public_settings_slug_key ON public.cafe_public_settings USING btree (slug)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_public_settings.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_public_settings","permissive":"PERMISSIVE","policyname":"cafe_public_settings_owner_write","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_public_settings.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"},{"cmd":"SELECT","qual":"(slug = 'thirsty-panda'::text)","roles":["anon","authenticated"],"tablename":"cafe_public_settings","permissive":"PERMISSIVE","policyname":"cafe_public_settings_public_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"cafe_public_settings_clover_status_check","definition":"CHECK (clover_status = ANY (ARRAY['setup_required'::text, 'connected'::text, 'disabled'::text]))"},{"name":"cafe_public_settings_pkey","definition":"PRIMARY KEY (tenant_org_id)"},{"name":"cafe_public_settings_slug_key","definition":"UNIQUE (slug)"},{"name":"cafe_public_settings_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"cafe_tables","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'available'::text","identity":"","not_null":true,"generated":""},{"name":"guest_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cafe_tables_pkey","definition":"CREATE UNIQUE INDEX cafe_tables_pkey ON public.cafe_tables USING btree (id)"},{"name":"cafe_tables_tenant_org_id_label_key","definition":"CREATE UNIQUE INDEX cafe_tables_tenant_org_id_label_key ON public.cafe_tables USING btree (tenant_org_id, label)"},{"name":"cafe_tables_tenant_sort_idx","definition":"CREATE INDEX cafe_tables_tenant_sort_idx ON public.cafe_tables USING btree (tenant_org_id, sort_order)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_tables.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["authenticated"],"tablename":"cafe_tables","permissive":"PERMISSIVE","policyname":"cafe_tables_owner_access","schemaname":"public","with_check":"(is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND (membership.tenant_id = cafe_tables.tenant_org_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"cafe_tables_guest_count_check","definition":"CHECK (guest_count >= 0)"},{"name":"cafe_tables_pkey","definition":"PRIMARY KEY (id)"},{"name":"cafe_tables_status_check","definition":"CHECK (status = ANY (ARRAY['available'::text, 'seated'::text, 'reserved'::text, 'cleaning'::text]))"},{"name":"cafe_tables_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"cafe_tables_tenant_org_id_label_key","definition":"UNIQUE (tenant_org_id, label)"}]},{"table":"call_assist_pushes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"pushed_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"kind","type":"text","default":"'script'::text","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_assist_pushes_pkey","definition":"CREATE UNIQUE INDEX call_assist_pushes_pkey ON public.call_assist_pushes USING btree (id)"},{"name":"idx_call_assist_pushes_rep_unack","definition":"CREATE INDEX idx_call_assist_pushes_rep_unack ON public.call_assist_pushes USING btree (rep_id, acknowledged_at) WHERE (acknowledged_at IS NULL)"},{"name":"idx_call_assist_pushes_session","definition":"CREATE INDEX idx_call_assist_pushes_session ON public.call_assist_pushes USING btree (active_call_session_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_assist_pushes","permissive":"PERMISSIVE","policyname":"cap_insert_manager","schemaname":"public","with_check":"((pushed_by = uid()) AND ((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin()))"},{"cmd":"SELECT","qual":"((rep_id = uid()) OR (is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["authenticated"],"tablename":"call_assist_pushes","permissive":"PERMISSIVE","policyname":"cap_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(rep_id = uid())","roles":["authenticated"],"tablename":"call_assist_pushes","permissive":"PERMISSIVE","policyname":"cap_update_ack","schemaname":"public","with_check":"(rep_id = uid())"}],"triggers":[],"constraints":[{"name":"call_assist_pushes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_assist_suggestions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"confidence","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"acted_on","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_assist_suggestions_pkey","definition":"CREATE UNIQUE INDEX call_assist_suggestions_pkey ON public.call_assist_suggestions USING btree (id)"},{"name":"idx_call_assist_suggestions_session","definition":"CREATE INDEX idx_call_assist_suggestions_session ON public.call_assist_suggestions USING btree (active_call_session_id, created_at DESC)"},{"name":"idx_call_assist_suggestions_tenant_lead","definition":"CREATE INDEX idx_call_assist_suggestions_tenant_lead ON public.call_assist_suggestions USING btree (tenant_org_id, lead_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"call_assist_suggestions","permissive":"PERMISSIVE","policyname":"tenant_members_read_call_assist_suggestions","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"call_assist_suggestions","permissive":"PERMISSIVE","policyname":"tenant_members_update_acted_on","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"}],"triggers":[],"constraints":[{"name":"call_assist_suggestions_kind_check","definition":"CHECK (kind = ANY (ARRAY['objection'::text, 'dnc'::text, 'script_stage'::text, 'final'::text, 'error'::text]))"},{"name":"call_assist_suggestions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_attempts_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempt_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"was_inbound","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"call_log_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_attempts_log_pkey","definition":"CREATE UNIQUE INDEX call_attempts_log_pkey ON public.call_attempts_log USING btree (id)"},{"name":"idx_call_attempts_lead","definition":"CREATE INDEX idx_call_attempts_lead ON public.call_attempts_log USING btree (lead_id, created_at DESC)"},{"name":"idx_call_attempts_tenant_phone_time","definition":"CREATE INDEX idx_call_attempts_tenant_phone_time ON public.call_attempts_log USING btree (tenant_org_id, phone_normalized, created_at DESC) WHERE (was_inbound = false)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_attempts_log","permissive":"PERMISSIVE","policyname":"tenant_members_insert_attempts","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"call_attempts_log","permissive":"PERMISSIVE","policyname":"tenant_members_view_attempts","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"call_attempts_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_campaigns_pkey","definition":"CREATE UNIQUE INDEX call_campaigns_pkey ON public.call_campaigns USING btree (id)"},{"name":"idx_call_campaigns_tenant","definition":"CREATE INDEX idx_call_campaigns_tenant ON public.call_campaigns USING btree (tenant_org_id)"}],"policies":[{"cmd":"ALL","qual":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"call_campaigns","permissive":"PERMISSIVE","policyname":"campaigns_admin_write","schemaname":"public","with_check":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"call_campaigns","permissive":"PERMISSIVE","policyname":"campaigns_select_tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_call_campaigns_updated_at","definition":"CREATE TRIGGER trg_call_campaigns_updated_at BEFORE UPDATE ON call_campaigns FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"call_campaigns_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_lifecycle_events","schema":"public","columns":[{"name":"id","type":"bigint","default":"nextval('call_lifecycle_events_id_seq'::regclass)","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_lifecycle_events_pkey","definition":"CREATE UNIQUE INDEX call_lifecycle_events_pkey ON public.call_lifecycle_events USING btree (id)"},{"name":"idx_cle_session","definition":"CREATE INDEX idx_cle_session ON public.call_lifecycle_events USING btree (session_id, created_at DESC)"},{"name":"idx_cle_tenant_recent","definition":"CREATE INDEX idx_cle_tenant_recent ON public.call_lifecycle_events USING btree (tenant_org_id, created_at DESC)"},{"name":"idx_cle_user_recent","definition":"CREATE INDEX idx_cle_user_recent ON public.call_lifecycle_events USING btree (user_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_lifecycle_events","permissive":"PERMISSIVE","policyname":"cle_insert_self","schemaname":"public","with_check":"((user_id IS NULL) OR (user_id = uid()))"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), tenant_org_id)))","roles":["authenticated"],"tablename":"call_lifecycle_events","permissive":"PERMISSIVE","policyname":"cle_select_admins_or_self","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"call_lifecycle_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_called","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"outcome","type":"call_outcome","default":null,"identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"callback_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"lead_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"direction","type":"text","default":"'outbound'::text","identity":"","not_null":true,"generated":""},{"name":"twilio_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"disclosure_played","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"disclosure_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"disclosure_timestamp","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"compliance_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"disclosure_confirmed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcript","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcription_received_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"bridge_confirmation","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"call_logs_pkey","definition":"CREATE UNIQUE INDEX call_logs_pkey ON public.call_logs USING btree (id)"},{"name":"idx_call_logs_contact","definition":"CREATE INDEX idx_call_logs_contact ON public.call_logs USING btree (contact_id) WHERE (contact_id IS NOT NULL)"},{"name":"idx_call_logs_created_at","definition":"CREATE INDEX idx_call_logs_created_at ON public.call_logs USING btree (created_at DESC)"},{"name":"idx_call_logs_lead_id","definition":"CREATE INDEX idx_call_logs_lead_id ON public.call_logs USING btree (lead_id)"},{"name":"idx_call_logs_lead_outcome","definition":"CREATE INDEX idx_call_logs_lead_outcome ON public.call_logs USING btree (lead_id, outcome)"},{"name":"idx_call_logs_outcome","definition":"CREATE INDEX idx_call_logs_outcome ON public.call_logs USING btree (outcome)"},{"name":"idx_call_logs_phone","definition":"CREATE INDEX idx_call_logs_phone ON public.call_logs USING btree (phone_called)"},{"name":"idx_call_logs_tenant_created","definition":"CREATE INDEX idx_call_logs_tenant_created ON public.call_logs USING btree (tenant_id, created_at DESC)"},{"name":"idx_call_logs_tenant_id","definition":"CREATE INDEX idx_call_logs_tenant_id ON public.call_logs USING btree (tenant_id)"},{"name":"idx_call_logs_twilio_sid","definition":"CREATE INDEX idx_call_logs_twilio_sid ON public.call_logs USING btree (twilio_call_sid) WHERE (twilio_call_sid IS NOT NULL)"},{"name":"idx_call_logs_user_id","definition":"CREATE INDEX idx_call_logs_user_id ON public.call_logs USING btree (user_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = call_logs.tenant_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["authenticated"],"tablename":"call_logs","permissive":"PERMISSIVE","policyname":"Admins can view all tenant call logs","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_logs","permissive":"PERMISSIVE","policyname":"Users can insert own call logs","schemaname":"public","with_check":"((user_id = uid()) AND (tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))))"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"call_logs","permissive":"PERMISSIVE","policyname":"Users can update own call logs","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"call_logs","permissive":"PERMISSIVE","policyname":"Users can view own call logs","schemaname":"public","with_check":null}],"triggers":[{"name":"audit_trigger_call_logs","definition":"CREATE TRIGGER audit_trigger_call_logs AFTER INSERT OR DELETE OR UPDATE ON call_logs FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"},{"name":"update_call_logs_updated_at","definition":"CREATE TRIGGER update_call_logs_updated_at BEFORE UPDATE ON call_logs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"call_logs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_qa_reviews","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"call_log_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"reviewer_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"sentiment","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"flagged","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"coaching_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tags","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_qa_reviews_pkey","definition":"CREATE UNIQUE INDEX call_qa_reviews_pkey ON public.call_qa_reviews USING btree (id)"},{"name":"idx_call_qa_call","definition":"CREATE INDEX idx_call_qa_call ON public.call_qa_reviews USING btree (call_log_id)"},{"name":"idx_call_qa_rep","definition":"CREATE INDEX idx_call_qa_rep ON public.call_qa_reviews USING btree (rep_id)"},{"name":"idx_call_qa_tenant","definition":"CREATE INDEX idx_call_qa_tenant ON public.call_qa_reviews USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"DELETE","qual":"((reviewer_id = uid()) AND is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"call_qa_reviews","permissive":"PERMISSIVE","policyname":"Tenant managers delete QA reviews","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_qa_reviews","permissive":"PERMISSIVE","policyname":"Tenant managers insert QA reviews","schemaname":"public","with_check":"((reviewer_id = uid()) AND is_tenant_member(uid(), tenant_id) AND (EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = call_qa_reviews.tenant_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))"},{"cmd":"UPDATE","qual":"((reviewer_id = uid()) AND is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"call_qa_reviews","permissive":"PERMISSIVE","policyname":"Tenant managers update QA reviews","schemaname":"public","with_check":"(reviewer_id = uid())"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) AND ((EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = call_qa_reviews.tenant_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))) OR (rep_id = uid())))","roles":["authenticated"],"tablename":"call_qa_reviews","permissive":"PERMISSIVE","policyname":"Tenant managers view QA reviews","schemaname":"public","with_check":null}],"triggers":[{"name":"update_call_qa_reviews_updated_at","definition":"CREATE TRIGGER update_call_qa_reviews_updated_at BEFORE UPDATE ON call_qa_reviews FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"call_qa_reviews_pkey","definition":"PRIMARY KEY (id)"},{"name":"call_qa_reviews_score_check","definition":"CHECK (score >= 1 AND score <= 5)"},{"name":"call_qa_reviews_sentiment_check","definition":"CHECK (sentiment = ANY (ARRAY['positive'::text, 'neutral'::text, 'negative'::text]))"}]},{"table":"call_queue","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assignment_source","type":"text","default":"'admin_curated'::text","identity":"","not_null":true,"generated":""},{"name":"priority","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"last_attempt_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_attempt_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempt_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_queue_pkey","definition":"CREATE UNIQUE INDEX call_queue_pkey ON public.call_queue USING btree (id)"},{"name":"idx_call_queue_rep","definition":"CREATE INDEX idx_call_queue_rep ON public.call_queue USING btree (rep_id, status, priority DESC)"},{"name":"idx_call_queue_tenant","definition":"CREATE INDEX idx_call_queue_tenant ON public.call_queue USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"call_queue","permissive":"PERMISSIVE","policyname":"queue_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"call_queue","permissive":"PERMISSIVE","policyname":"queue_admin_insert","schemaname":"public","with_check":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())"},{"cmd":"SELECT","qual":"((rep_id = uid()) OR (is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"call_queue","permissive":"PERMISSIVE","policyname":"queue_rep_select_own","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((rep_id = uid()) OR (is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"call_queue","permissive":"PERMISSIVE","policyname":"queue_rep_update_own","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_call_queue_updated_at","definition":"CREATE TRIGGER trg_call_queue_updated_at BEFORE UPDATE ON call_queue FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"call_queue_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_recordings","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_url","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"channels","type":"integer","default":"1","identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'live_call'::text","identity":"","not_null":true,"generated":""},{"name":"ai_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_sentiment","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_topics","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"ai_action_items","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"ai_outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"ai_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"analyzed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"call_recordings_pkey","definition":"CREATE UNIQUE INDEX call_recordings_pkey ON public.call_recordings USING btree (id)"},{"name":"call_recordings_recording_sid_key","definition":"CREATE UNIQUE INDEX call_recordings_recording_sid_key ON public.call_recordings USING btree (recording_sid)"},{"name":"idx_call_recordings_session","definition":"CREATE INDEX idx_call_recordings_session ON public.call_recordings USING btree (active_call_session_id)"},{"name":"idx_call_recordings_status","definition":"CREATE INDEX idx_call_recordings_status ON public.call_recordings USING btree (ai_status) WHERE (ai_status = ANY (ARRAY['pending'::text, 'processing'::text]))"},{"name":"idx_call_recordings_tenant","definition":"CREATE INDEX idx_call_recordings_tenant ON public.call_recordings USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) AND is_manager_or_higher(uid(), (tenant_org_id)::uuid))","roles":["authenticated"],"tablename":"call_recordings","permissive":"PERMISSIVE","policyname":"managers_write_call_recordings","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) AND is_manager_or_higher(uid(), (tenant_org_id)::uuid))"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"call_recordings","permissive":"PERMISSIVE","policyname":"tenant_members_read_call_recordings","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"call_recordings_ai_score_check","definition":"CHECK (ai_score >= 0 AND ai_score <= 100 OR ai_score IS NULL)"},{"name":"call_recordings_ai_sentiment_check","definition":"CHECK ((ai_sentiment = ANY (ARRAY['positive'::text, 'neutral'::text, 'negative'::text, 'urgent'::text])) OR ai_sentiment IS NULL)"},{"name":"call_recordings_ai_status_check","definition":"CHECK (ai_status = ANY (ARRAY['pending'::text, 'processing'::text, 'complete'::text, 'failed'::text, 'skipped'::text]))"},{"name":"call_recordings_pkey","definition":"PRIMARY KEY (id)"},{"name":"call_recordings_recording_sid_key","definition":"UNIQUE (recording_sid)"},{"name":"call_recordings_source_check","definition":"CHECK (source = ANY (ARRAY['live_call'::text, 'voicemail'::text, 'transfer'::text, 'conference'::text]))"}]},{"table":"call_scripts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenancy_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"script_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"script_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"script_content","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"prompts","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_template","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"derived_from_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"adopted_admin_version","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"call_scripts_pkey","definition":"CREATE UNIQUE INDEX call_scripts_pkey ON public.call_scripts USING btree (id)"},{"name":"call_scripts_unique_per_tenant","definition":"CREATE UNIQUE INDEX call_scripts_unique_per_tenant ON public.call_scripts USING btree (tenant_org_id, tenancy_type, script_type, script_name)"},{"name":"idx_call_scripts_template","definition":"CREATE INDEX idx_call_scripts_template ON public.call_scripts USING btree (is_template, tenancy_type) WHERE (is_template = true)"},{"name":"ux_call_scripts_tenant_type_name_active","definition":"CREATE UNIQUE INDEX ux_call_scripts_tenant_type_name_active ON public.call_scripts USING btree (tenant_org_id, tenancy_type, script_name) WHERE (is_active = true)"}],"policies":[{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND (is_system_admin(uid()) OR is_tenant_owner_for(uid(), tenant_org_id)))","roles":["public"],"tablename":"call_scripts","permissive":"PERMISSIVE","policyname":"Tenant owners manage tenant scripts","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(((tenant_org_id IS NULL) AND (is_template = true)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = call_scripts.tenant_org_id)))))","roles":["public"],"tablename":"call_scripts","permissive":"PERMISSIVE","policyname":"Users view tenant scripts and templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"call_scripts","permissive":"PERMISSIVE","policyname":"call_scripts_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"call_scripts","permissive":"PERMISSIVE","policyname":"call_scripts_tenant_member_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"call_scripts","permissive":"PERMISSIVE","policyname":"call_scripts_tenant_owner_manage","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))"}],"triggers":[],"constraints":[{"name":"call_scripts_pkey","definition":"PRIMARY KEY (id)"},{"name":"call_scripts_unique_per_tenant","definition":"UNIQUE (tenant_org_id, tenancy_type, script_type, script_name)"}]},{"table":"call_summaries","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"summary","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"generated_by","type":"text","default":"'post-call-summarize'::text","identity":"","not_null":true,"generated":""},{"name":"applied","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_summaries_contact_idx","definition":"CREATE INDEX call_summaries_contact_idx ON public.call_summaries USING btree (contact_id, created_at DESC)"},{"name":"call_summaries_lead_idx","definition":"CREATE INDEX call_summaries_lead_idx ON public.call_summaries USING btree (lead_id, created_at DESC)"},{"name":"call_summaries_pkey","definition":"CREATE UNIQUE INDEX call_summaries_pkey ON public.call_summaries USING btree (id)"},{"name":"call_summaries_session_uniq","definition":"CREATE UNIQUE INDEX call_summaries_session_uniq ON public.call_summaries USING btree (active_call_session_id)"},{"name":"call_summaries_tenant_idx","definition":"CREATE INDEX call_summaries_tenant_idx ON public.call_summaries USING btree (tenant_org_id, active_call_session_id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member((tenant_org_id)::text)","roles":["authenticated"],"tablename":"call_summaries","permissive":"PERMISSIVE","policyname":"tenant members read summaries","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_call_summaries_touch","definition":"CREATE TRIGGER trg_call_summaries_touch BEFORE UPDATE ON call_summaries FOR EACH ROW EXECUTE FUNCTION touch_call_summaries_updated_at()"}],"constraints":[{"name":"call_summaries_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_supervision_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"parent_call_sid","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"conference_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"supervisor_user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"supervised_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"mode","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"supervisor_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"ended_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_supervision_sessions_pkey","definition":"CREATE UNIQUE INDEX call_supervision_sessions_pkey ON public.call_supervision_sessions USING btree (id)"},{"name":"idx_supervision_parent","definition":"CREATE INDEX idx_supervision_parent ON public.call_supervision_sessions USING btree (parent_call_sid)"},{"name":"idx_supervision_supervisor","definition":"CREATE INDEX idx_supervision_supervisor ON public.call_supervision_sessions USING btree (supervisor_user_id)"},{"name":"idx_supervision_tenant","definition":"CREATE INDEX idx_supervision_tenant ON public.call_supervision_sessions USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_supervision_sessions","permissive":"PERMISSIVE","policyname":"Managers+ can insert supervision sessions","schemaname":"public","with_check":"(is_manager_or_higher(uid(), tenant_org_id) AND (supervisor_user_id = uid()))"},{"cmd":"UPDATE","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"call_supervision_sessions","permissive":"PERMISSIVE","policyname":"Managers+ can update supervision sessions","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"call_supervision_sessions","permissive":"PERMISSIVE","policyname":"Managers+ can view supervision sessions","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_supervision_updated","definition":"CREATE TRIGGER trg_supervision_updated BEFORE UPDATE ON call_supervision_sessions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"call_supervision_sessions_mode_check","definition":"CHECK (mode = ANY (ARRAY['monitor'::text, 'whisper'::text, 'barge'::text]))"},{"name":"call_supervision_sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"call_supervision_sessions_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'ended'::text, 'failed'::text]))"}]},{"table":"call_transcript_segments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_stream_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_stream_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parent_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"track","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"speaker","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"transcript","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_final","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"confidence","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"ended_at_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"sequence_number","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_transcript_segments_pkey","definition":"CREATE UNIQUE INDEX call_transcript_segments_pkey ON public.call_transcript_segments USING btree (id)"},{"name":"idx_cts_lead_created","definition":"CREATE INDEX idx_cts_lead_created ON public.call_transcript_segments USING btree (lead_id, created_at)"},{"name":"idx_cts_stream_sid","definition":"CREATE INDEX idx_cts_stream_sid ON public.call_transcript_segments USING btree (twilio_stream_sid)"},{"name":"idx_cts_tenant_session_created","definition":"CREATE INDEX idx_cts_tenant_session_created ON public.call_transcript_segments USING btree (tenant_org_id, active_call_session_id, created_at)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"call_transcript_segments","permissive":"PERMISSIVE","policyname":"tenant members can read transcript segments","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"call_transcript_segments_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_transcripts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_final","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"start_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"end_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"confidence","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_transcripts_pkey","definition":"CREATE UNIQUE INDEX call_transcripts_pkey ON public.call_transcripts USING btree (id)"},{"name":"idx_call_transcripts_session","definition":"CREATE INDEX idx_call_transcripts_session ON public.call_transcripts USING btree (active_call_session_id, created_at)"},{"name":"idx_call_transcripts_tenant_lead","definition":"CREATE INDEX idx_call_transcripts_tenant_lead ON public.call_transcripts USING btree (tenant_org_id, lead_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"call_transcripts","permissive":"PERMISSIVE","policyname":"tenant_members_read_call_transcripts","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"call_transcripts_channel_check","definition":"CHECK (channel = ANY (ARRAY['rep'::text, 'homeowner'::text, 'unknown'::text]))"},{"name":"call_transcripts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"call_transfers","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"parent_call_sid","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"conference_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transfer_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"initiated_by_user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"target_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_extension","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_external_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'initiated'::text","identity":"","not_null":true,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"call_transfers_pkey","definition":"CREATE UNIQUE INDEX call_transfers_pkey ON public.call_transfers USING btree (id)"},{"name":"idx_call_transfers_initiator","definition":"CREATE INDEX idx_call_transfers_initiator ON public.call_transfers USING btree (initiated_by_user_id)"},{"name":"idx_call_transfers_parent","definition":"CREATE INDEX idx_call_transfers_parent ON public.call_transfers USING btree (parent_call_sid)"},{"name":"idx_call_transfers_target_user","definition":"CREATE INDEX idx_call_transfers_target_user ON public.call_transfers USING btree (target_user_id)"},{"name":"idx_call_transfers_tenant","definition":"CREATE INDEX idx_call_transfers_tenant ON public.call_transfers USING btree (tenant_org_id)"}],"policies":[{"cmd":"UPDATE","qual":"((initiated_by_user_id = uid()) OR is_manager_or_higher(uid(), tenant_org_id))","roles":["authenticated"],"tablename":"call_transfers","permissive":"PERMISSIVE","policyname":"Initiator or managers+ can update transfers","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((initiated_by_user_id = uid()) OR (target_user_id = uid()) OR is_manager_or_higher(uid(), tenant_org_id))","roles":["authenticated"],"tablename":"call_transfers","permissive":"PERMISSIVE","policyname":"Initiator or managers+ can view transfers","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"call_transfers","permissive":"PERMISSIVE","policyname":"Tenant members can insert their own transfers","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) AND ((initiated_by_user_id = uid()) OR is_manager_or_higher(uid(), tenant_org_id)))"}],"triggers":[{"name":"trg_call_transfers_updated","definition":"CREATE TRIGGER trg_call_transfers_updated BEFORE UPDATE ON call_transfers FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"call_transfers_check","definition":"CHECK (target_user_id IS NOT NULL OR target_extension IS NOT NULL OR target_external_number IS NOT NULL)"},{"name":"call_transfers_pkey","definition":"PRIMARY KEY (id)"},{"name":"call_transfers_status_check","definition":"CHECK (status = ANY (ARRAY['initiated'::text, 'ringing'::text, 'consult'::text, 'completed'::text, 'cancelled'::text, 'failed'::text, 'no_answer'::text]))"},{"name":"call_transfers_transfer_type_check","definition":"CHECK (transfer_type = ANY (ARRAY['warm'::text, 'cold'::text, 'conference'::text]))"}]},{"table":"canvasser_breadcrumbs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"accuracy_m","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"captured_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"day_key","type":"date","default":"((now() AT TIME ZONE 'UTC'::text))::date","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"canvasser_breadcrumbs_pkey","definition":"CREATE UNIQUE INDEX canvasser_breadcrumbs_pkey ON public.canvasser_breadcrumbs USING btree (id)"},{"name":"idx_breadcrumbs_tenant_day","definition":"CREATE INDEX idx_breadcrumbs_tenant_day ON public.canvasser_breadcrumbs USING btree (tenant_org_id, day_key, captured_at)"},{"name":"idx_breadcrumbs_user_time","definition":"CREATE INDEX idx_breadcrumbs_user_time ON public.canvasser_breadcrumbs USING btree (user_id, captured_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"canvasser_breadcrumbs","permissive":"PERMISSIVE","policyname":"Reps insert own breadcrumbs","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"canvasser_breadcrumbs","permissive":"PERMISSIVE","policyname":"Reps view own breadcrumbs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = canvasser_breadcrumbs.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["authenticated"],"tablename":"canvasser_breadcrumbs","permissive":"PERMISSIVE","policyname":"Tenant managers view all tenant breadcrumbs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"canvasser_breadcrumbs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"canvasser_locations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"heading","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"accuracy","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_seen","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"canvasser_locations_pkey","definition":"CREATE UNIQUE INDEX canvasser_locations_pkey ON public.canvasser_locations USING btree (id)"},{"name":"canvasser_locations_user_id_tenant_org_id_key","definition":"CREATE UNIQUE INDEX canvasser_locations_user_id_tenant_org_id_key ON public.canvasser_locations USING btree (user_id, tenant_org_id)"},{"name":"idx_canvasser_locations_tenant","definition":"CREATE INDEX idx_canvasser_locations_tenant ON public.canvasser_locations USING btree (tenant_org_id, last_seen DESC)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = canvasser_locations.tenant_org_id) AND (utm.status = 'active'::text))))","roles":["authenticated"],"tablename":"canvasser_locations","permissive":"PERMISSIVE","policyname":"Tenant members can view team locations","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = canvasser_locations.tenant_org_id) AND (utm.status = 'active'::text)))))","roles":["authenticated"],"tablename":"canvasser_locations","permissive":"PERMISSIVE","policyname":"Users delete their own location","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"canvasser_locations","permissive":"PERMISSIVE","policyname":"Users insert their own location","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = canvasser_locations.tenant_org_id) AND (utm.status = 'active'::text)))))"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"canvasser_locations","permissive":"PERMISSIVE","policyname":"Users update their own location","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = canvasser_locations.tenant_org_id) AND (utm.status = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"canvasser_locations_pkey","definition":"PRIMARY KEY (id)"},{"name":"canvasser_locations_user_id_tenant_org_id_key","definition":"UNIQUE (user_id, tenant_org_id)"}]},{"table":"canvassing_batch_operations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"operation_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"door_ids","type":"uuid[]","default":null,"identity":"","not_null":true,"generated":""},{"name":"parameters","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"result","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"executed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_batch_operations_pkey","definition":"CREATE UNIQUE INDEX canvassing_batch_operations_pkey ON public.canvassing_batch_operations USING btree (id)"},{"name":"idx_batch_ops_user","definition":"CREATE INDEX idx_batch_ops_user ON public.canvassing_batch_operations USING btree (user_id, executed_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(((uid())::text = user_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_batch_operations","permissive":"PERMISSIVE","policyname":"Users manage own batch operations","schemaname":"public","with_check":"(((uid())::text = user_id) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"canvassing_batch_operations_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"canvassing_check_ins","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"territory_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_in_time","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"expected_end_time","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"actual_end_time","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_in_location","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_heartbeat","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"panic_triggered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"panic_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_check_ins_pkey","definition":"CREATE UNIQUE INDEX canvassing_check_ins_pkey ON public.canvassing_check_ins USING btree (id)"},{"name":"idx_check_ins_status","definition":"CREATE INDEX idx_check_ins_status ON public.canvassing_check_ins USING btree (status)"},{"name":"idx_check_ins_tenant","definition":"CREATE INDEX idx_check_ins_tenant ON public.canvassing_check_ins USING btree (tenant_org_id)"},{"name":"idx_check_ins_user_id","definition":"CREATE INDEX idx_check_ins_user_id ON public.canvassing_check_ins USING btree (user_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"canvassing_check_ins","permissive":"PERMISSIVE","policyname":"Users insert own check-ins","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["public"],"tablename":"canvassing_check_ins","permissive":"PERMISSIVE","policyname":"Users update own check-ins","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"canvassing_check_ins","permissive":"PERMISSIVE","policyname":"Users view own check-ins","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"canvassing_check_ins_pkey","definition":"PRIMARY KEY (id)"},{"name":"canvassing_check_ins_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'completed'::text, 'overdue'::text, 'panic'::text]))"}]},{"table":"canvassing_goals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"date","type":"date","default":"CURRENT_DATE","identity":"","not_null":true,"generated":""},{"name":"target_doors","type":"integer","default":"50","identity":"","not_null":false,"generated":""},{"name":"completed_doors","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"target_appointments","type":"integer","default":"5","identity":"","not_null":false,"generated":""},{"name":"completed_appointments","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"target_interested","type":"integer","default":"10","identity":"","not_null":false,"generated":""},{"name":"completed_interested","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_goals_pkey","definition":"CREATE UNIQUE INDEX canvassing_goals_pkey ON public.canvassing_goals USING btree (id)"},{"name":"canvassing_goals_user_id_date_key","definition":"CREATE UNIQUE INDEX canvassing_goals_user_id_date_key ON public.canvassing_goals USING btree (user_id, date)"},{"name":"idx_goals_tenant","definition":"CREATE INDEX idx_goals_tenant ON public.canvassing_goals USING btree (tenant_org_id, date DESC)"},{"name":"idx_goals_user_date","definition":"CREATE INDEX idx_goals_user_date ON public.canvassing_goals USING btree (user_id, date DESC)"}],"policies":[{"cmd":"ALL","qual":"(((uid())::text = user_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_goals","permissive":"PERMISSIVE","policyname":"Users manage own canvassing goals","schemaname":"public","with_check":"(((uid())::text = user_id) OR is_system_admin(uid()))"},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"canvassing_goals","permissive":"PERMISSIVE","policyname":"cg_all","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"canvassing_goals_pkey","definition":"PRIMARY KEY (id)"},{"name":"canvassing_goals_user_id_date_key","definition":"UNIQUE (user_id, date)"}]},{"table":"canvassing_leaderboard","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"period","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_start","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_end","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"doors_knocked","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"appointments_set","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"interested_contacts","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"not_home_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"total_distance_km","type":"numeric(10,2)","default":"0","identity":"","not_null":false,"generated":""},{"name":"avg_time_per_door","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_leaderboard_pkey","definition":"CREATE UNIQUE INDEX canvassing_leaderboard_pkey ON public.canvassing_leaderboard USING btree (id)"},{"name":"canvassing_leaderboard_user_id_period_period_start_key","definition":"CREATE UNIQUE INDEX canvassing_leaderboard_user_id_period_period_start_key ON public.canvassing_leaderboard USING btree (user_id, period, period_start)"},{"name":"idx_leaderboard_period","definition":"CREATE INDEX idx_leaderboard_period ON public.canvassing_leaderboard USING btree (tenant_org_id, period, period_start DESC)"},{"name":"idx_leaderboard_ranking","definition":"CREATE INDEX idx_leaderboard_ranking ON public.canvassing_leaderboard USING btree (tenant_org_id, period, doors_knocked DESC)"}],"policies":[{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_leaderboard","permissive":"PERMISSIVE","policyname":"Tenant members read leaderboard","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((uid())::text = user_id)","roles":["public"],"tablename":"canvassing_leaderboard","permissive":"PERMISSIVE","policyname":"canvassing_leaderboard_update_policy","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"canvassing_leaderboard","permissive":"PERMISSIVE","policyname":"canvassing_leaderboard_write_policy","schemaname":"public","with_check":"((uid())::text = user_id)"},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"canvassing_leaderboard","permissive":"PERMISSIVE","policyname":"clb_all","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"canvassing_leaderboard_pkey","definition":"PRIMARY KEY (id)"},{"name":"canvassing_leaderboard_user_id_period_period_start_key","definition":"UNIQUE (user_id, period, period_start)"}]},{"table":"canvassing_live_locations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"current_door_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"route_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_live_locations_pkey","definition":"CREATE UNIQUE INDEX canvassing_live_locations_pkey ON public.canvassing_live_locations USING btree (id)"},{"name":"canvassing_live_locations_user_id_tenant_org_id_key","definition":"CREATE UNIQUE INDEX canvassing_live_locations_user_id_tenant_org_id_key ON public.canvassing_live_locations USING btree (user_id, tenant_org_id)"},{"name":"idx_live_locations_tenant","definition":"CREATE INDEX idx_live_locations_tenant ON public.canvassing_live_locations USING btree (tenant_org_id, updated_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"((tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE (utm.user_id = uid()))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_live_locations","permissive":"PERMISSIVE","policyname":"Tenant members view live locations","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((user_id = (uid())::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_live_locations","permissive":"PERMISSIVE","policyname":"Users delete their own location","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"canvassing_live_locations","permissive":"PERMISSIVE","policyname":"Users insert their own location","schemaname":"public","with_check":"((user_id = (uid())::text) AND (tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE (utm.user_id = uid()))))"},{"cmd":"UPDATE","qual":"(user_id = (uid())::text)","roles":["authenticated"],"tablename":"canvassing_live_locations","permissive":"PERMISSIVE","policyname":"Users update their own location","schemaname":"public","with_check":"(user_id = (uid())::text)"}],"triggers":[],"constraints":[{"name":"canvassing_live_locations_pkey","definition":"PRIMARY KEY (id)"},{"name":"canvassing_live_locations_user_id_tenant_org_id_key","definition":"UNIQUE (user_id, tenant_org_id)"}]},{"table":"canvassing_recontacts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scheduled_for","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"priority","type":"integer","default":"1","identity":"","not_null":false,"generated":""},{"name":"completed","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"text","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"canvassing_recontacts_pkey","definition":"CREATE UNIQUE INDEX canvassing_recontacts_pkey ON public.canvassing_recontacts USING btree (id)"},{"name":"idx_recontacts_door","definition":"CREATE INDEX idx_recontacts_door ON public.canvassing_recontacts USING btree (door_id)"},{"name":"idx_recontacts_priority","definition":"CREATE INDEX idx_recontacts_priority ON public.canvassing_recontacts USING btree (tenant_org_id, priority DESC, scheduled_for)"},{"name":"idx_recontacts_scheduled","definition":"CREATE INDEX idx_recontacts_scheduled ON public.canvassing_recontacts USING btree (assigned_to, scheduled_for, completed)"}],"policies":[{"cmd":"ALL","qual":"(((uid())::text = assigned_to) OR ((uid())::text = created_by) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_recontacts","permissive":"PERMISSIVE","policyname":"Tenant members manage recontacts","schemaname":"public","with_check":"(((uid())::text = assigned_to) OR ((uid())::text = created_by) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"canvassing_recontacts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"canvassing_routes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"territory_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"door_ids","type":"uuid[]","default":null,"identity":"","not_null":true,"generated":""},{"name":"optimized_order","type":"integer[]","default":null,"identity":"","not_null":true,"generated":""},{"name":"total_distance_meters","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimated_time_minutes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_routes_pkey","definition":"CREATE UNIQUE INDEX canvassing_routes_pkey ON public.canvassing_routes USING btree (id)"},{"name":"idx_routes_status","definition":"CREATE INDEX idx_routes_status ON public.canvassing_routes USING btree (status, user_id)"},{"name":"idx_routes_territory","definition":"CREATE INDEX idx_routes_territory ON public.canvassing_routes USING btree (territory_id)"},{"name":"idx_routes_user","definition":"CREATE INDEX idx_routes_user ON public.canvassing_routes USING btree (user_id, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(((uid())::text = user_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"canvassing_routes","permissive":"PERMISSIVE","policyname":"Users manage own canvassing routes","schemaname":"public","with_check":"(((uid())::text = user_id) OR is_system_admin(uid()))"},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"canvassing_routes","permissive":"PERMISSIVE","policyname":"cr_all","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"canvassing_routes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"canvassing_safe_zones","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"polygon_geojson","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"zone_type","type":"text","default":"'safe'::text","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"canvassing_safe_zones_pkey","definition":"CREATE UNIQUE INDEX canvassing_safe_zones_pkey ON public.canvassing_safe_zones USING btree (id)"},{"name":"idx_safe_zones_tenant","definition":"CREATE INDEX idx_safe_zones_tenant ON public.canvassing_safe_zones USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = canvassing_safe_zones.tenant_org_id))))","roles":["public"],"tablename":"canvassing_safe_zones","permissive":"PERMISSIVE","policyname":"Tenant members view safe zones","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"canvassing_safe_zones_pkey","definition":"PRIMARY KEY (id)"},{"name":"canvassing_safe_zones_zone_type_check","definition":"CHECK (zone_type = ANY (ARRAY['safe'::text, 'restricted'::text, 'avoid'::text]))"}]},{"table":"card_grading_cards","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"submission_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"cert_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sequence_number","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"year","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"brand_set","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"player_character","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"card_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"variation","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"declared_value","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"grade","type":"numeric(4,1)","default":null,"identity":"","not_null":false,"generated":""},{"name":"grade_label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'received'::text","identity":"","not_null":true,"generated":""},{"name":"front_image_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"back_image_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"slab_image_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"grader_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"population_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"import_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_demo","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"card_grading_cards_pkey","definition":"CREATE UNIQUE INDEX card_grading_cards_pkey ON public.card_grading_cards USING btree (id)"},{"name":"card_grading_cards_tenant_id_cert_number_key","definition":"CREATE UNIQUE INDEX card_grading_cards_tenant_id_cert_number_key ON public.card_grading_cards USING btree (tenant_id, cert_number)"},{"name":"card_grading_cards_tenant_import_key_uidx","definition":"CREATE UNIQUE INDEX card_grading_cards_tenant_import_key_uidx ON public.card_grading_cards USING btree (tenant_id, import_key)"},{"name":"idx_card_grading_cards_cert","definition":"CREATE INDEX idx_card_grading_cards_cert ON public.card_grading_cards USING btree (tenant_id, cert_number)"},{"name":"idx_card_grading_cards_submission","definition":"CREATE INDEX idx_card_grading_cards_submission ON public.card_grading_cards USING btree (submission_id)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = card_grading_cards.tenant_id)))))","roles":["public"],"tablename":"card_grading_cards","permissive":"PERMISSIVE","policyname":"card_grading_cards_tenant_all","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = card_grading_cards.tenant_id)))))"}],"triggers":[],"constraints":[{"name":"card_grading_cards_pkey","definition":"PRIMARY KEY (id)"},{"name":"card_grading_cards_status_check","definition":"CHECK (status = ANY (ARRAY['received'::text, 'intake_imaging'::text, 'authentication'::text, 'grading'::text, 'encapsulation'::text, 'qa'::text, 'ready'::text, 'shipped'::text, 'picked_up'::text]))"},{"name":"card_grading_cards_submission_id_fkey","definition":"FOREIGN KEY (submission_id) REFERENCES card_grading_submissions(id) ON DELETE CASCADE"},{"name":"card_grading_cards_tenant_id_cert_number_key","definition":"UNIQUE (tenant_id, cert_number)"},{"name":"card_grading_cards_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"card_grading_submissions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"submission_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_tier","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"service_price","type":"numeric(10,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'received'::text","identity":"","not_null":true,"generated":""},{"name":"delivery_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tracking_in","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tracking_out","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"received_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"payment_status","type":"text","default":"'unverified'::text","identity":"","not_null":true,"generated":""},{"name":"payment_reference","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_demo","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"card_grading_submissions_pkey","definition":"CREATE UNIQUE INDEX card_grading_submissions_pkey ON public.card_grading_submissions USING btree (id)"},{"name":"card_grading_submissions_tenant_id_submission_number_key","definition":"CREATE UNIQUE INDEX card_grading_submissions_tenant_id_submission_number_key ON public.card_grading_submissions USING btree (tenant_id, submission_number)"},{"name":"idx_card_grading_submissions_due","definition":"CREATE INDEX idx_card_grading_submissions_due ON public.card_grading_submissions USING btree (tenant_id, due_at)"},{"name":"idx_card_grading_submissions_tenant_payment","definition":"CREATE INDEX idx_card_grading_submissions_tenant_payment ON public.card_grading_submissions USING btree (tenant_id, payment_status)"},{"name":"idx_card_grading_submissions_tenant_status","definition":"CREATE INDEX idx_card_grading_submissions_tenant_status ON public.card_grading_submissions USING btree (tenant_id, status)"}],"policies":[{"cmd":"ALL","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = card_grading_submissions.tenant_id)))))","roles":["public"],"tablename":"card_grading_submissions","permissive":"PERMISSIVE","policyname":"card_grading_submissions_tenant_all","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = card_grading_submissions.tenant_id)))))"}],"triggers":[],"constraints":[{"name":"card_grading_submissions_delivery_method_check","definition":"CHECK (delivery_method = ANY (ARRAY['walk_in'::text, 'mail_in'::text, 'ship_back'::text, 'pickup'::text]))"},{"name":"card_grading_submissions_payment_status_check","definition":"CHECK (payment_status = ANY (ARRAY['unverified'::text, 'manually_verified'::text, 'waived'::text, 'refunded'::text]))"},{"name":"card_grading_submissions_pkey","definition":"PRIMARY KEY (id)"},{"name":"card_grading_submissions_service_price_check","definition":"CHECK (service_price >= 0::numeric)"},{"name":"card_grading_submissions_service_tier_check","definition":"CHECK (service_tier = ANY (ARRAY['two_weeks'::text, 'one_week'::text, 'three_days'::text, 'same_day'::text, 'inventory'::text]))"},{"name":"card_grading_submissions_status_check","definition":"CHECK (status = ANY (ARRAY['received'::text, 'intake_imaging'::text, 'authentication'::text, 'grading'::text, 'encapsulation'::text, 'qa'::text, 'ready'::text, 'shipped'::text, 'picked_up'::text]))"},{"name":"card_grading_submissions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"card_grading_submissions_tenant_id_submission_number_key","definition":"UNIQUE (tenant_id, submission_number)"}]},{"table":"carrier_preferences","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"carrier_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"requires_line_item_photos","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"allows_op","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"op_min_claim_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"pays_code_upgrades","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"supplement_turnaround_days","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"preferred_submission_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"carrier_preferences_pkey","definition":"CREATE UNIQUE INDEX carrier_preferences_pkey ON public.carrier_preferences USING btree (id)"},{"name":"carrier_preferences_tenant_org_id_carrier_name_key","definition":"CREATE UNIQUE INDEX carrier_preferences_tenant_org_id_carrier_name_key ON public.carrier_preferences USING btree (tenant_org_id, carrier_name)"},{"name":"idx_carrier_preferences_tenant","definition":"CREATE INDEX idx_carrier_preferences_tenant ON public.carrier_preferences USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["public"],"tablename":"carrier_preferences","permissive":"PERMISSIVE","policyname":"tenant members delete carrier prefs","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"carrier_preferences","permissive":"PERMISSIVE","policyname":"tenant members insert carrier prefs","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["public"],"tablename":"carrier_preferences","permissive":"PERMISSIVE","policyname":"tenant members read carrier prefs","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["public"],"tablename":"carrier_preferences","permissive":"PERMISSIVE","policyname":"tenant members update carrier prefs","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_carrier_preferences_updated_at","definition":"CREATE TRIGGER trg_carrier_preferences_updated_at BEFORE UPDATE ON carrier_preferences FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"carrier_preferences_pkey","definition":"PRIMARY KEY (id)"},{"name":"carrier_preferences_tenant_org_id_carrier_name_key","definition":"UNIQUE (tenant_org_id, carrier_name)"}]},{"table":"case_documents_required","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_required","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'Missing'::text","identity":"","not_null":true,"generated":""},{"name":"linked_file_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"linked_file_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"case_documents_required_pkey","definition":"CREATE UNIQUE INDEX case_documents_required_pkey ON public.case_documents_required USING btree (id)"},{"name":"idx_case_docs_claim","definition":"CREATE INDEX idx_case_docs_claim ON public.case_documents_required USING btree (claim_id)"},{"name":"idx_case_docs_status","definition":"CREATE INDEX idx_case_docs_status ON public.case_documents_required USING btree (tenant_org_id, status)"},{"name":"idx_case_docs_tenant","definition":"CREATE INDEX idx_case_docs_tenant ON public.case_documents_required USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"case_documents_required","permissive":"PERMISSIVE","policyname":"case_docs_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"case_documents_required","permissive":"PERMISSIVE","policyname":"case_docs_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"case_documents_required","permissive":"PERMISSIVE","policyname":"case_docs_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"case_documents_required","permissive":"PERMISSIVE","policyname":"case_docs_update","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_case_docs_updated_at","definition":"CREATE TRIGGER trg_case_docs_updated_at BEFORE UPDATE ON case_documents_required FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"case_documents_required_pkey","definition":"PRIMARY KEY (id)"},{"name":"case_documents_required_status_check","definition":"CHECK (status = ANY (ARRAY['Missing'::text, 'Requested'::text, 'Received'::text, 'Verified'::text, 'Not Applicable'::text]))"}]},{"table":"challenge_participants","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"challenge_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_score","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"rank","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"progress","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"joined_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"challenge_participants_challenge_id_user_id_key","definition":"CREATE UNIQUE INDEX challenge_participants_challenge_id_user_id_key ON public.challenge_participants USING btree (challenge_id, user_id)"},{"name":"challenge_participants_pkey","definition":"CREATE UNIQUE INDEX challenge_participants_pkey ON public.challenge_participants USING btree (id)"},{"name":"idx_challenge_participants_challenge","definition":"CREATE INDEX idx_challenge_participants_challenge ON public.challenge_participants USING btree (challenge_id)"},{"name":"idx_challenge_participants_user","definition":"CREATE INDEX idx_challenge_participants_user ON public.challenge_participants USING btree (user_id)"}],"policies":[{"cmd":"ALL","qual":"(uid() = user_id)","roles":["public"],"tablename":"challenge_participants","permissive":"PERMISSIVE","policyname":"Users manage own participation","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM challenges\n  WHERE (challenges.id = challenge_participants.challenge_id)))","roles":["public"],"tablename":"challenge_participants","permissive":"PERMISSIVE","policyname":"Users view challenge participants","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"challenge_participants_challenge_id_user_id_key","definition":"UNIQUE (challenge_id, user_id)"},{"name":"challenge_participants_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"challenges","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"challenge_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"start_date","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"end_date","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"rules","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"reward_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'upcoming'::text","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"challenges_pkey","definition":"CREATE UNIQUE INDEX challenges_pkey ON public.challenges USING btree (id)"},{"name":"idx_challenges_status","definition":"CREATE INDEX idx_challenges_status ON public.challenges USING btree (status)"},{"name":"idx_challenges_tenant","definition":"CREATE INDEX idx_challenges_tenant ON public.challenges USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = challenges.tenant_org_id))))","roles":["public"],"tablename":"challenges","permissive":"PERMISSIVE","policyname":"Tenant members view challenges","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"challenges_pkey","definition":"PRIMARY KEY (id)"},{"name":"challenges_status_check","definition":"CHECK (status = ANY (ARRAY['upcoming'::text, 'active'::text, 'completed'::text, 'cancelled'::text]))"}]},{"table":"claim_deadlines","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"due_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'Open'::text","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_statutory","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"priority","type":"text","default":"'Medium'::text","identity":"","not_null":true,"generated":""},{"name":"assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"due_time","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deadline_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"cancelled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"claim_deadlines_pkey","definition":"CREATE UNIQUE INDEX claim_deadlines_pkey ON public.claim_deadlines USING btree (id)"},{"name":"idx_claim_deadlines_assigned_user","definition":"CREATE INDEX idx_claim_deadlines_assigned_user ON public.claim_deadlines USING btree (assigned_user_id) WHERE (assigned_user_id IS NOT NULL)"},{"name":"idx_claim_deadlines_claim","definition":"CREATE INDEX idx_claim_deadlines_claim ON public.claim_deadlines USING btree (claim_id)"},{"name":"idx_claim_deadlines_due","definition":"CREATE INDEX idx_claim_deadlines_due ON public.claim_deadlines USING btree (due_date) WHERE (status = 'Open'::text)"},{"name":"idx_claim_deadlines_open","definition":"CREATE INDEX idx_claim_deadlines_open ON public.claim_deadlines USING btree (tenant_org_id, status, due_date) WHERE (status = 'Open'::text)"},{"name":"idx_claim_deadlines_tenant","definition":"CREATE INDEX idx_claim_deadlines_tenant ON public.claim_deadlines USING btree (tenant_org_id)"},{"name":"idx_claim_deadlines_tenant_due","definition":"CREATE INDEX idx_claim_deadlines_tenant_due ON public.claim_deadlines USING btree (tenant_org_id, due_date)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_deadlines","permissive":"PERMISSIVE","policyname":"deadlines_delete_tenant_or_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"claim_deadlines","permissive":"PERMISSIVE","policyname":"deadlines_insert_tenant_or_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_tenant_member(tenant_org_id) OR is_system_admin(uid())))"},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND (uid() IS NOT NULL))","roles":["authenticated"],"tablename":"claim_deadlines","permissive":"RESTRICTIVE","policyname":"deadlines_restrict_null_or_anon","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (uid() IS NOT NULL))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_deadlines","permissive":"PERMISSIVE","policyname":"deadlines_select_tenant_or_admin","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_deadlines","permissive":"PERMISSIVE","policyname":"deadlines_update_tenant_or_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_tenant_member(tenant_org_id) OR is_system_admin(uid())))"}],"triggers":[{"name":"trg_mark_late_deadlines","definition":"CREATE TRIGGER trg_mark_late_deadlines BEFORE INSERT OR UPDATE ON claim_deadlines FOR EACH ROW EXECUTE FUNCTION mark_late_deadlines()"},{"name":"update_claim_deadlines_updated_at","definition":"CREATE TRIGGER update_claim_deadlines_updated_at BEFORE UPDATE ON claim_deadlines FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"claim_deadlines_pkey","definition":"PRIMARY KEY (id)"},{"name":"claim_deadlines_priority_check","definition":"CHECK (priority = ANY (ARRAY['Low'::text, 'Medium'::text, 'High'::text, 'Critical'::text]))"}]},{"table":"claim_negotiation_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"who","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_date","type":"date","default":"CURRENT_DATE","identity":"","not_null":true,"generated":""},{"name":"next_action_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"attachment_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"carrier_offer_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"pa_demand_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"settlement_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimate_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"made_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"received_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"communication_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_followup_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"claim_negotiation_events_pkey","definition":"CREATE UNIQUE INDEX claim_negotiation_events_pkey ON public.claim_negotiation_events USING btree (id)"},{"name":"idx_claim_neg_tenant_date","definition":"CREATE INDEX idx_claim_neg_tenant_date ON public.claim_negotiation_events USING btree (tenant_org_id, event_date DESC)"},{"name":"idx_negotiation_claim","definition":"CREATE INDEX idx_negotiation_claim ON public.claim_negotiation_events USING btree (claim_id, event_date DESC)"},{"name":"idx_negotiation_tenant","definition":"CREATE INDEX idx_negotiation_tenant ON public.claim_negotiation_events USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_negotiation_events","permissive":"PERMISSIVE","policyname":"negotiation_delete_tenant_or_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"claim_negotiation_events","permissive":"PERMISSIVE","policyname":"negotiation_insert_tenant_or_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_tenant_member(tenant_org_id) OR is_system_admin(uid())))"},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND (uid() IS NOT NULL))","roles":["authenticated"],"tablename":"claim_negotiation_events","permissive":"RESTRICTIVE","policyname":"negotiation_restrict_null_or_anon","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (uid() IS NOT NULL))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_negotiation_events","permissive":"PERMISSIVE","policyname":"negotiation_select_tenant_or_admin","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_negotiation_events","permissive":"PERMISSIVE","policyname":"negotiation_update_tenant_or_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_tenant_member(tenant_org_id) OR is_system_admin(uid())))"}],"triggers":[{"name":"update_negotiation_updated_at","definition":"CREATE TRIGGER update_negotiation_updated_at BEFORE UPDATE ON claim_negotiation_events FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"claim_negotiation_events_communication_method_check","definition":"CHECK (communication_method IS NULL OR (communication_method = ANY (ARRAY['call'::text, 'email'::text, 'letter'::text, 'portal'::text, 'in-person'::text, 'other'::text])))"},{"name":"claim_negotiation_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"claim_payment_status_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_status","type":"claim_payment_lifecycle_v4","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_status","type":"claim_payment_lifecycle_v4","default":null,"identity":"","not_null":true,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"claim_payment_status_history_pkey","definition":"CREATE UNIQUE INDEX claim_payment_status_history_pkey ON public.claim_payment_status_history USING btree (id)"},{"name":"idx_cpsh_claim_id_changed_at","definition":"CREATE INDEX idx_cpsh_claim_id_changed_at ON public.claim_payment_status_history USING btree (claim_id, changed_at DESC)"},{"name":"idx_cpsh_tenant","definition":"CREATE INDEX idx_cpsh_tenant ON public.claim_payment_status_history USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR is_manager_or_higher(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"claim_payment_status_history","permissive":"PERMISSIVE","policyname":"Manager+ can view claim payment history","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"claim_payment_status_history_pkey","definition":"PRIMARY KEY (id)"},{"name":"claim_payment_status_history_source_check","definition":"CHECK (source = ANY (ARRAY['manual'::text, 'backfill'::text, 'system'::text]))"}]},{"table":"claim_supplements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"supplement_number","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"amount_requested","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"amount_approved","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"gaps_snapshot","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"letter_html","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recipient_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recipient_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"responded_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"claim_supplements_claim_number_unique","definition":"CREATE UNIQUE INDEX claim_supplements_claim_number_unique ON public.claim_supplements USING btree (claim_id, supplement_number)"},{"name":"claim_supplements_pkey","definition":"CREATE UNIQUE INDEX claim_supplements_pkey ON public.claim_supplements USING btree (id)"},{"name":"idx_claim_supplements_claim","definition":"CREATE INDEX idx_claim_supplements_claim ON public.claim_supplements USING btree (claim_id)"},{"name":"idx_claim_supplements_contact","definition":"CREATE INDEX idx_claim_supplements_contact ON public.claim_supplements USING btree (contact_id)"},{"name":"idx_claim_supplements_tenant","definition":"CREATE INDEX idx_claim_supplements_tenant ON public.claim_supplements USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"claim_supplements","permissive":"PERMISSIVE","policyname":"tenant members delete supplements","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"claim_supplements","permissive":"PERMISSIVE","policyname":"tenant members insert supplements","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"claim_supplements","permissive":"PERMISSIVE","policyname":"tenant members read supplements","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"claim_supplements","permissive":"PERMISSIVE","policyname":"tenant members update supplements","schemaname":"public","with_check":null}],"triggers":[{"name":"update_claim_supplements_updated_at","definition":"CREATE TRIGGER update_claim_supplements_updated_at BEFORE UPDATE ON claim_supplements FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"claim_supplements_claim_number_unique","definition":"UNIQUE (claim_id, supplement_number)"},{"name":"claim_supplements_pkey","definition":"PRIMARY KEY (id)"},{"name":"claim_supplements_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'sent'::text, 'partial-approved'::text, 'approved'::text, 'denied'::text, 'withdrawn'::text]))"}]},{"table":"claim_valuation_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"quantity","type":"numeric","default":"1","identity":"","not_null":true,"generated":""},{"name":"unit_cost","type":"numeric","default":"0","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"shared_claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"claim_valuation_items_pkey","definition":"CREATE UNIQUE INDEX claim_valuation_items_pkey ON public.claim_valuation_items USING btree (id)"},{"name":"claim_valuation_items_shared_claim_idx","definition":"CREATE INDEX claim_valuation_items_shared_claim_idx ON public.claim_valuation_items USING btree (tenant_org_id, shared_claim_id) WHERE (shared_claim_id IS NOT NULL)"},{"name":"idx_claim_valuation_items_claim","definition":"CREATE INDEX idx_claim_valuation_items_claim ON public.claim_valuation_items USING btree (claim_id, created_at)"},{"name":"idx_claim_valuation_items_tenant","definition":"CREATE INDEX idx_claim_valuation_items_tenant ON public.claim_valuation_items USING btree (tenant_org_id, contact_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"claim_valuation_items","permissive":"PERMISSIVE","policyname":"Tenant members can create claim valuation items","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_valuation_items","permissive":"PERMISSIVE","policyname":"Tenant members can delete claim valuation items","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_valuation_items","permissive":"PERMISSIVE","policyname":"Tenant members can update claim valuation items","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"claim_valuation_items","permissive":"PERMISSIVE","policyname":"Tenant members can view claim valuation items","schemaname":"public","with_check":null}],"triggers":[{"name":"update_claim_valuation_items_updated_at","definition":"CREATE TRIGGER update_claim_valuation_items_updated_at BEFORE UPDATE ON claim_valuation_items FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"claim_valuation_items_claim_id_fkey","definition":"FOREIGN KEY (claim_id) REFERENCES contact_claims(id) ON DELETE CASCADE"},{"name":"claim_valuation_items_claim_reference_check","definition":"CHECK ((claim_id IS NOT NULL) <> (shared_claim_id IS NOT NULL))"},{"name":"claim_valuation_items_created_by_fkey","definition":"FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL"},{"name":"claim_valuation_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"claim_valuation_items_quantity_check","definition":"CHECK (quantity > 0::numeric)"},{"name":"claim_valuation_items_shared_claim_id_fkey","definition":"FOREIGN KEY (shared_claim_id) REFERENCES shared_claims(id) ON DELETE CASCADE"},{"name":"claim_valuation_items_unit_cost_check","definition":"CHECK (unit_cost >= 0::numeric)"}]},{"table":"code_audit_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"rule_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"pattern_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_pattern","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"code_pattern","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"severity","type":"text","default":"'warning'::text","identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"last_scanned_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"violations_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"code_audit_rules_pkey","definition":"CREATE UNIQUE INDEX code_audit_rules_pkey ON public.code_audit_rules USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"code_audit_rules","permissive":"PERMISSIVE","policyname":"platform_admin_manage_code_audit","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"code_audit_rules_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"cohort_definitions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"character varying(255)","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"cohort_type","type":"character varying(50)","default":null,"identity":"","not_null":true,"generated":""},{"name":"definition","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"cohort_definitions_pkey","definition":"CREATE UNIQUE INDEX cohort_definitions_pkey ON public.cohort_definitions USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"cohort_definitions","permissive":"PERMISSIVE","policyname":"Users can manage cohorts","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"cohort_definitions","permissive":"PERMISSIVE","policyname":"Users can view own tenant cohorts","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"cohort_definitions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"command_center_activity_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"command_center_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"old_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"actor_type","type":"text","default":"'human'::text","identity":"","not_null":true,"generated":""},{"name":"actor_agent_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"command_center_activity_log_pkey","definition":"CREATE UNIQUE INDEX command_center_activity_log_pkey ON public.command_center_activity_log USING btree (id)"},{"name":"idx_ccal_event","definition":"CREATE INDEX idx_ccal_event ON public.command_center_activity_log USING btree (command_center_event_id, created_at)"},{"name":"idx_ccal_platform_created","definition":"CREATE INDEX idx_ccal_platform_created ON public.command_center_activity_log USING btree (created_at DESC) WHERE (tenant_id IS NULL)"},{"name":"idx_ccal_tenant","definition":"CREATE INDEX idx_ccal_tenant ON public.command_center_activity_log USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM command_center_events e\n  WHERE ((e.id = command_center_activity_log.command_center_event_id) AND is_tenant_member(uid(), e.tenant_id) AND (is_command_agent(uid(), e.tenant_id) OR (e.created_by_user_id = uid()) OR (e.assigned_to_user_id = uid())))))","roles":["authenticated"],"tablename":"command_center_activity_log","permissive":"PERMISSIVE","policyname":"ccal_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"command_center_activity_log_action_type_check","definition":"CHECK (action_type = ANY (ARRAY['acknowledged'::text, 'approval_decision'::text, 'approval_pending'::text, 'assigned'::text, 'closed'::text, 'created'::text, 'deploy_dispatched'::text, 'escalated'::text, 'owner_notified'::text, 'owner_notify_failed'::text, 'replied'::text, 'repo_pr_closed'::text, 'reported_by_agent'::text, 'resolved'::text, 'status_changed'::text, 'event_resolved_by_cleanup'::text, 'sql_ops_executed'::text]))"},{"name":"command_center_activity_log_actor_type_check","definition":"CHECK (actor_type = ANY (ARRAY['human'::text, 'agent'::text, 'system'::text]))"},{"name":"command_center_activity_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"command_center_agent_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"agent_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"agent_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"route","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"method","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status_code","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"latency_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_agent_runs_pkey","definition":"CREATE UNIQUE INDEX command_center_agent_runs_pkey ON public.command_center_agent_runs USING btree (id)"},{"name":"idx_ccar_agent_created","definition":"CREATE INDEX idx_ccar_agent_created ON public.command_center_agent_runs USING btree (agent_id, created_at DESC)"},{"name":"idx_ccar_status","definition":"CREATE INDEX idx_ccar_status ON public.command_center_agent_runs USING btree (status_code)"},{"name":"idx_ccar_tenant_created","definition":"CREATE INDEX idx_ccar_tenant_created ON public.command_center_agent_runs USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"command_center_agent_runs","permissive":"PERMISSIVE","policyname":"ccar_godmode_select","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((tenant_id IS NOT NULL) AND is_command_agent(uid(), tenant_id))","roles":["authenticated"],"tablename":"command_center_agent_runs","permissive":"PERMISSIVE","policyname":"ccar_tenant_admin_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"command_center_agent_runs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"command_center_agent_tenants","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"agent_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"access_level","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_agent_tenants_agent_id_tenant_id_key","definition":"CREATE UNIQUE INDEX command_center_agent_tenants_agent_id_tenant_id_key ON public.command_center_agent_tenants USING btree (agent_id, tenant_id)"},{"name":"command_center_agent_tenants_pkey","definition":"CREATE UNIQUE INDEX command_center_agent_tenants_pkey ON public.command_center_agent_tenants USING btree (id)"},{"name":"idx_ccat_agent","definition":"CREATE INDEX idx_ccat_agent ON public.command_center_agent_tenants USING btree (agent_id)"},{"name":"idx_ccat_tenant","definition":"CREATE INDEX idx_ccat_tenant ON public.command_center_agent_tenants USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"command_center_agent_tenants","permissive":"PERMISSIVE","policyname":"ccat_godmode_all","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"command_center_agent_tenants_access_level_check","definition":"CHECK (access_level = ANY (ARRAY['read'::text, 'triage'::text, 'admin'::text]))"},{"name":"command_center_agent_tenants_agent_id_tenant_id_key","definition":"UNIQUE (agent_id, tenant_id)"},{"name":"command_center_agent_tenants_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"command_center_agents","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scopes","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":true,"generated":""},{"name":"platform_scope","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"api_key_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"api_key_prefix","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rate_limit_per_min","type":"integer","default":"60","identity":"","not_null":true,"generated":""},{"name":"enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"disabled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"rotated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_used_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_agents_api_key_hash_key","definition":"CREATE UNIQUE INDEX command_center_agents_api_key_hash_key ON public.command_center_agents USING btree (api_key_hash)"},{"name":"command_center_agents_name_key","definition":"CREATE UNIQUE INDEX command_center_agents_name_key ON public.command_center_agents USING btree (name)"},{"name":"command_center_agents_pkey","definition":"CREATE UNIQUE INDEX command_center_agents_pkey ON public.command_center_agents USING btree (id)"},{"name":"idx_cc_agents_enabled","definition":"CREATE INDEX idx_cc_agents_enabled ON public.command_center_agents USING btree (enabled)"},{"name":"idx_cc_agents_role","definition":"CREATE INDEX idx_cc_agents_role ON public.command_center_agents USING btree (role)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"command_center_agents","permissive":"PERMISSIVE","policyname":"cca_godmode_all","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"command_center_agents","permissive":"PERMISSIVE","policyname":"cca_godmode_select","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_cca_updated_at","definition":"CREATE TRIGGER trg_cca_updated_at BEFORE UPDATE ON command_center_agents FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"command_center_agents_api_key_hash_key","definition":"UNIQUE (api_key_hash)"},{"name":"command_center_agents_name_key","definition":"UNIQUE (name)"},{"name":"command_center_agents_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_agents_role_check","definition":"CHECK (role = ANY (ARRAY['worker'::text, 'commander'::text, 'approval_gate'::text]))"}]},{"table":"command_center_deploy_approvals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"agent_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"function_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"head_sha","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"consumed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_deploy_approvals_pkey","definition":"CREATE UNIQUE INDEX command_center_deploy_approvals_pkey ON public.command_center_deploy_approvals USING btree (id)"},{"name":"command_center_deploy_approvals_token_hash_key","definition":"CREATE UNIQUE INDEX command_center_deploy_approvals_token_hash_key ON public.command_center_deploy_approvals USING btree (token_hash)"},{"name":"idx_cc_deploy_approvals_expires","definition":"CREATE INDEX idx_cc_deploy_approvals_expires ON public.command_center_deploy_approvals USING btree (expires_at) WHERE (consumed_at IS NULL)"}],"policies":[{"cmd":"ALL","qual":"true","roles":["service_role"],"tablename":"command_center_deploy_approvals","permissive":"PERMISSIVE","policyname":"service_role full access cc_deploy_approvals","schemaname":"public","with_check":"true"}],"triggers":[],"constraints":[{"name":"command_center_deploy_approvals_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_deploy_approvals_token_hash_key","definition":"UNIQUE (token_hash)"}]},{"table":"command_center_dispatch_jobs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"agent_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"function_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"workflow","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"head_sha","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"run_id","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"run_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"run_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"run_conclusion","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"dispatched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"command_center_dispatch_jobs_one_active_deploy_per_target_idx","definition":"CREATE UNIQUE INDEX command_center_dispatch_jobs_one_active_deploy_per_target_idx ON public.command_center_dispatch_jobs USING btree (function_name, workflow) WHERE ((kind = 'deploy_function'::text) AND (status = ANY (ARRAY['pending'::text, 'dispatched'::text, 'running'::text])))"},{"name":"command_center_dispatch_jobs_pkey","definition":"CREATE UNIQUE INDEX command_center_dispatch_jobs_pkey ON public.command_center_dispatch_jobs USING btree (id)"},{"name":"idx_ccdj_agent_created","definition":"CREATE INDEX idx_ccdj_agent_created ON public.command_center_dispatch_jobs USING btree (agent_id, created_at DESC)"},{"name":"idx_ccdj_status","definition":"CREATE INDEX idx_ccdj_status ON public.command_center_dispatch_jobs USING btree (status, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"false","roles":["authenticated"],"tablename":"command_center_dispatch_jobs","permissive":"PERMISSIVE","policyname":"no client access","schemaname":"public","with_check":"false"}],"triggers":[],"constraints":[{"name":"command_center_dispatch_jobs_kind_check","definition":"CHECK (kind = ANY (ARRAY['deploy_function'::text, 'function_logs'::text, 'deploy_status'::text]))"},{"name":"command_center_dispatch_jobs_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_dispatch_jobs_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'dispatched'::text, 'in_progress'::text, 'succeeded'::text, 'failed'::text, 'expired'::text]))"}]},{"table":"command_center_event_artifacts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"command_center_event_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"artifact_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"storage_bucket","type":"text","default":"'command-center-visual-witness'::text","identity":"","not_null":true,"generated":""},{"name":"storage_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"mime_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"width","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"height","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"device_pixel_ratio","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"route","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_marker","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by_role","type":"text","default":"'visual-witness-extension'::text","identity":"","not_null":true,"generated":""},{"name":"safe_metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_event_artifacts_pkey","definition":"CREATE UNIQUE INDEX command_center_event_artifacts_pkey ON public.command_center_event_artifacts USING btree (id)"},{"name":"command_center_event_artifacts_storage_path_unique","definition":"CREATE UNIQUE INDEX command_center_event_artifacts_storage_path_unique ON public.command_center_event_artifacts USING btree (storage_bucket, storage_path)"},{"name":"idx_ccea_event_created","definition":"CREATE INDEX idx_ccea_event_created ON public.command_center_event_artifacts USING btree (command_center_event_id, created_at DESC)"},{"name":"idx_ccea_tenant_created","definition":"CREATE INDEX idx_ccea_tenant_created ON public.command_center_event_artifacts USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"command_center_event_artifacts","permissive":"PERMISSIVE","policyname":"ccea_no_client_insert","schemaname":"public","with_check":"false"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM command_center_events e\n  WHERE ((e.id = command_center_event_artifacts.command_center_event_id) AND (e.tenant_id = command_center_event_artifacts.tenant_id) AND is_tenant_member(uid(), e.tenant_id) AND (is_command_agent(uid(), e.tenant_id) OR (e.created_by_user_id = uid()) OR (e.assigned_to_user_id = uid())))))","roles":["authenticated"],"tablename":"command_center_event_artifacts","permissive":"PERMISSIVE","policyname":"ccea_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"command_center_event_artifacts_artifact_type_check","definition":"CHECK (artifact_type = 'visible_tab_screenshot'::text)"},{"name":"command_center_event_artifacts_command_center_event_id_fkey","definition":"FOREIGN KEY (command_center_event_id) REFERENCES command_center_events(id) ON DELETE CASCADE"},{"name":"command_center_event_artifacts_mime_type_check","definition":"CHECK (mime_type = ANY (ARRAY['image/png'::text, 'image/jpeg'::text]))"},{"name":"command_center_event_artifacts_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_event_artifacts_storage_path_unique","definition":"UNIQUE (storage_bucket, storage_path)"}]},{"table":"command_center_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by_role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_module","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"related_lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_job_request_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_job_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"priority","type":"text","default":"'info'::text","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'new'::text","identity":"","not_null":true,"generated":""},{"name":"assigned_to_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"requires_response","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"acknowledged_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"requires_approval","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"approval_status","type":"text","default":"'n/a'::text","identity":"","not_null":true,"generated":""},{"name":"approval_decided_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_decided_by_agent_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_decided_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_decision_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_agent_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_type","type":"text","default":"'human'::text","identity":"","not_null":true,"generated":""},{"name":"actor_agent_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mission_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mission_phase","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mission_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_authorized","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"authorization_scope","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_step","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"attempt_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"leased_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lease_expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_progress_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"queue_deadline","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"execution_deadline","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"terminal_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"final_receipt","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"mission_context","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_events_pkey","definition":"CREATE UNIQUE INDEX command_center_events_pkey ON public.command_center_events USING btree (id)"},{"name":"idx_cce_active_missions","definition":"CREATE INDEX idx_cce_active_missions ON public.command_center_events USING btree (mission_status, last_progress_at, created_at) WHERE (mission_status = ANY (ARRAY['accepted'::text, 'queued'::text, 'pending'::text, 'running'::text, 'waiting'::text, 'retryable'::text]))"},{"name":"idx_cce_approval_pending","definition":"CREATE INDEX idx_cce_approval_pending ON public.command_center_events USING btree (tenant_id, created_at DESC) WHERE (approval_status = 'pending'::text)"},{"name":"idx_cce_creator","definition":"CREATE INDEX idx_cce_creator ON public.command_center_events USING btree (created_by_user_id)"},{"name":"idx_cce_mission_lease","definition":"CREATE INDEX idx_cce_mission_lease ON public.command_center_events USING btree (lease_expires_at) WHERE (leased_by IS NOT NULL)"},{"name":"idx_cce_owner_mission_key","definition":"CREATE UNIQUE INDEX idx_cce_owner_mission_key ON public.command_center_events USING btree (((mission_context ->> 'mission_key'::text))) WHERE ((event_type = 'owner_mission'::text) AND (mission_context ? 'mission_key'::text))"},{"name":"idx_cce_related_job","definition":"CREATE INDEX idx_cce_related_job ON public.command_center_events USING btree (related_job_id) WHERE (related_job_id IS NOT NULL)"},{"name":"idx_cce_related_lead","definition":"CREATE INDEX idx_cce_related_lead ON public.command_center_events USING btree (related_lead_id) WHERE (related_lead_id IS NOT NULL)"},{"name":"idx_cce_source_agent","definition":"CREATE INDEX idx_cce_source_agent ON public.command_center_events USING btree (source_agent_id) WHERE (source_agent_id IS NOT NULL)"},{"name":"idx_cce_tenant_assignee_status","definition":"CREATE INDEX idx_cce_tenant_assignee_status ON public.command_center_events USING btree (tenant_id, assigned_to_user_id, status)"},{"name":"idx_cce_tenant_status_priority_created","definition":"CREATE INDEX idx_cce_tenant_status_priority_created ON public.command_center_events USING btree (tenant_id, status, priority, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"command_center_events","permissive":"PERMISSIVE","policyname":"cce_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_id) AND (created_by_user_id = uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) AND (is_command_agent(uid(), tenant_id) OR (created_by_user_id = uid()) OR (assigned_to_user_id = uid()) OR (EXISTS ( SELECT 1\n   FROM unified_contacts uc\n  WHERE ((uc.id = command_center_events.related_lead_id) AND (uc.assigned_user = (uid())::text)))) OR (EXISTS ( SELECT 1\n   FROM jobs j\n  WHERE ((j.id = command_center_events.related_job_id) AND ((j.assigned_crew_id = uid()) OR (j.assigned_pm_id = uid())))))))","roles":["authenticated"],"tablename":"command_center_events","permissive":"PERMISSIVE","policyname":"cce_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_command_agent(uid(), tenant_id)","roles":["authenticated"],"tablename":"command_center_events","permissive":"PERMISSIVE","policyname":"cce_update","schemaname":"public","with_check":"is_command_agent(uid(), tenant_id)"}],"triggers":[{"name":"trg_cce_apply_approval_gate","definition":"CREATE TRIGGER trg_cce_apply_approval_gate BEFORE INSERT ON command_center_events FOR EACH ROW EXECUTE FUNCTION cce_apply_approval_gate()"},{"name":"trg_cce_dispatch_owner_alert_ins","definition":"CREATE TRIGGER trg_cce_dispatch_owner_alert_ins AFTER INSERT ON command_center_events FOR EACH ROW EXECUTE FUNCTION cce_dispatch_owner_alert()"},{"name":"trg_cce_dispatch_owner_alert_upd","definition":"CREATE TRIGGER trg_cce_dispatch_owner_alert_upd AFTER UPDATE OF priority, requires_approval, approval_status, event_type ON command_center_events FOR EACH ROW EXECUTE FUNCTION cce_dispatch_owner_alert()"},{"name":"trg_cce_on_insert","definition":"CREATE TRIGGER trg_cce_on_insert AFTER INSERT ON command_center_events FOR EACH ROW EXECUTE FUNCTION cce_on_insert()"},{"name":"trg_cce_on_update","definition":"CREATE TRIGGER trg_cce_on_update AFTER UPDATE ON command_center_events FOR EACH ROW EXECUTE FUNCTION cce_on_update()"},{"name":"trg_cce_updated_at","definition":"CREATE TRIGGER trg_cce_updated_at BEFORE UPDATE ON command_center_events FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"cce_actor_present","definition":"CHECK (actor_type = 'human'::text AND created_by_user_id IS NOT NULL OR actor_type = 'agent'::text AND actor_agent_id IS NOT NULL OR actor_type = 'system'::text)"},{"name":"command_center_events_actor_type_check","definition":"CHECK (actor_type = ANY (ARRAY['human'::text, 'agent'::text, 'system'::text]))"},{"name":"command_center_events_approval_status_check","definition":"CHECK (approval_status = ANY (ARRAY['n/a'::text, 'pending'::text, 'approved'::text, 'rejected'::text, 'needs_changes'::text]))"},{"name":"command_center_events_mission_status_check","definition":"CHECK (mission_status IS NULL OR (mission_status = ANY (ARRAY['accepted'::text, 'queued'::text, 'pending'::text, 'running'::text, 'waiting'::text, 'retryable'::text, 'verified'::text, 'completed_with_findings'::text, 'blocked'::text, 'failed'::text, 'timed_out'::text, 'cancelled'::text, 'superseded'::text])))"},{"name":"command_center_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_events_priority_check","definition":"CHECK (priority = ANY (ARRAY['info'::text, 'task'::text, 'urgent'::text, 'blocker'::text]))"},{"name":"command_center_events_source_module_check","definition":"CHECK (source_module = ANY (ARRAY['lead'::text, 'job_request'::text, 'job'::text, 'claim'::text, 'crew'::text, 'phone'::text, 'canvassing'::text, 'website'::text, 'ai'::text, 'system'::text, 'command_center'::text]))"},{"name":"command_center_events_status_check","definition":"CHECK (status = ANY (ARRAY['new'::text, 'acknowledged'::text, 'assigned'::text, 'in_progress'::text, 'pending_approval'::text, 'resolved'::text, 'closed'::text]))"}]},{"table":"command_center_messages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"command_center_event_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"sender_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"sender_role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"actor_type","type":"text","default":"'human'::text","identity":"","not_null":true,"generated":""},{"name":"actor_agent_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"command_center_messages_pkey","definition":"CREATE UNIQUE INDEX command_center_messages_pkey ON public.command_center_messages USING btree (id)"},{"name":"idx_ccm_event","definition":"CREATE INDEX idx_ccm_event ON public.command_center_messages USING btree (command_center_event_id, created_at)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"command_center_messages","permissive":"PERMISSIVE","policyname":"ccm_insert","schemaname":"public","with_check":"((sender_user_id = uid()) AND (EXISTS ( SELECT 1\n   FROM command_center_events e\n  WHERE ((e.id = command_center_messages.command_center_event_id) AND (e.tenant_id = command_center_messages.tenant_id) AND is_tenant_member(uid(), e.tenant_id) AND (is_command_agent(uid(), e.tenant_id) OR (e.created_by_user_id = uid()) OR (e.assigned_to_user_id = uid()) OR (EXISTS ( SELECT 1\n           FROM unified_contacts uc\n          WHERE ((uc.id = e.related_lead_id) AND (uc.assigned_user = (uid())::text)))) OR (EXISTS ( SELECT 1\n           FROM jobs j\n          WHERE ((j.id = e.related_job_id) AND ((j.assigned_crew_id = uid()) OR (j.assigned_pm_id = uid()))))))))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM command_center_events e\n  WHERE ((e.id = command_center_messages.command_center_event_id) AND is_tenant_member(uid(), e.tenant_id) AND (is_command_agent(uid(), e.tenant_id) OR (e.created_by_user_id = uid()) OR (e.assigned_to_user_id = uid()) OR (EXISTS ( SELECT 1\n           FROM unified_contacts uc\n          WHERE ((uc.id = e.related_lead_id) AND (uc.assigned_user = (uid())::text)))) OR (EXISTS ( SELECT 1\n           FROM jobs j\n          WHERE ((j.id = e.related_job_id) AND ((j.assigned_crew_id = uid()) OR (j.assigned_pm_id = uid())))))))))","roles":["authenticated"],"tablename":"command_center_messages","permissive":"PERMISSIVE","policyname":"ccm_select","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_ccm_on_insert","definition":"CREATE TRIGGER trg_ccm_on_insert AFTER INSERT ON command_center_messages FOR EACH ROW EXECUTE FUNCTION ccm_on_insert()"}],"constraints":[{"name":"ccm_actor_present","definition":"CHECK (actor_type = 'human'::text AND sender_user_id IS NOT NULL OR actor_type = 'agent'::text AND actor_agent_id IS NOT NULL OR actor_type = 'system'::text)"},{"name":"command_center_messages_actor_type_check","definition":"CHECK (actor_type = ANY (ARRAY['human'::text, 'agent'::text, 'system'::text]))"},{"name":"command_center_messages_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"command_center_mission_steps","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"command_center_event_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"step_order","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"step_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lane","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"attempt_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"idempotency_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"input","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"output","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_progress_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deadline_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_mission_steps_command_center_event_id_step_k_key","definition":"CREATE UNIQUE INDEX command_center_mission_steps_command_center_event_id_step_k_key ON public.command_center_mission_steps USING btree (command_center_event_id, step_key)"},{"name":"command_center_mission_steps_idempotency_key_key","definition":"CREATE UNIQUE INDEX command_center_mission_steps_idempotency_key_key ON public.command_center_mission_steps USING btree (idempotency_key)"},{"name":"command_center_mission_steps_pkey","definition":"CREATE UNIQUE INDEX command_center_mission_steps_pkey ON public.command_center_mission_steps USING btree (id)"},{"name":"idx_ccms_event_order","definition":"CREATE INDEX idx_ccms_event_order ON public.command_center_mission_steps USING btree (command_center_event_id, step_order)"},{"name":"idx_ccms_runnable","definition":"CREATE INDEX idx_ccms_runnable ON public.command_center_mission_steps USING btree (status, deadline_at, created_at) WHERE (status = ANY (ARRAY['ready'::text, 'running'::text, 'waiting'::text, 'retryable'::text]))"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"command_center_mission_steps","permissive":"PERMISSIVE","policyname":"ccms_insert","schemaname":"public","with_check":"is_command_agent(( SELECT uid() AS uid), tenant_id)"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM command_center_events e\n  WHERE ((e.id = command_center_mission_steps.command_center_event_id) AND is_command_agent(( SELECT uid() AS uid), e.tenant_id))))","roles":["authenticated"],"tablename":"command_center_mission_steps","permissive":"PERMISSIVE","policyname":"ccms_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_command_agent(( SELECT uid() AS uid), tenant_id)","roles":["authenticated"],"tablename":"command_center_mission_steps","permissive":"PERMISSIVE","policyname":"ccms_update","schemaname":"public","with_check":"is_command_agent(( SELECT uid() AS uid), tenant_id)"}],"triggers":[{"name":"trg_ccms_updated_at","definition":"CREATE TRIGGER trg_ccms_updated_at BEFORE UPDATE ON command_center_mission_steps FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"command_center_mission_steps_command_center_event_id_fkey","definition":"FOREIGN KEY (command_center_event_id) REFERENCES command_center_events(id) ON DELETE CASCADE"},{"name":"command_center_mission_steps_command_center_event_id_step_k_key","definition":"UNIQUE (command_center_event_id, step_key)"},{"name":"command_center_mission_steps_idempotency_key_key","definition":"UNIQUE (idempotency_key)"},{"name":"command_center_mission_steps_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_mission_steps_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'ready'::text, 'running'::text, 'waiting'::text, 'retryable'::text, 'verified'::text, 'completed_with_findings'::text, 'blocked'::text, 'failed'::text, 'timed_out'::text, 'cancelled'::text, 'skipped'::text, 'superseded'::text]))"}]},{"table":"command_center_receipts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"command_center_event_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"mission_step_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"receipt_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"proof_gate","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_sha","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"idempotency_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_receipts_idempotency_key_key","definition":"CREATE UNIQUE INDEX command_center_receipts_idempotency_key_key ON public.command_center_receipts USING btree (idempotency_key)"},{"name":"command_center_receipts_mission_step_id_idx","definition":"CREATE INDEX command_center_receipts_mission_step_id_idx ON public.command_center_receipts USING btree (mission_step_id)"},{"name":"command_center_receipts_pkey","definition":"CREATE UNIQUE INDEX command_center_receipts_pkey ON public.command_center_receipts USING btree (id)"},{"name":"idx_ccr_event_created","definition":"CREATE INDEX idx_ccr_event_created ON public.command_center_receipts USING btree (command_center_event_id, created_at DESC)"},{"name":"idx_ccr_external","definition":"CREATE INDEX idx_ccr_external ON public.command_center_receipts USING btree (source, external_id) WHERE (external_id IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM command_center_events e\n  WHERE ((e.id = command_center_receipts.command_center_event_id) AND is_command_agent(( SELECT uid() AS uid), e.tenant_id))))","roles":["authenticated"],"tablename":"command_center_receipts","permissive":"PERMISSIVE","policyname":"ccr_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"command_center_receipts_command_center_event_id_fkey","definition":"FOREIGN KEY (command_center_event_id) REFERENCES command_center_events(id) ON DELETE CASCADE"},{"name":"command_center_receipts_idempotency_key_key","definition":"UNIQUE (idempotency_key)"},{"name":"command_center_receipts_mission_step_id_fkey","definition":"FOREIGN KEY (mission_step_id) REFERENCES command_center_mission_steps(id) ON DELETE SET NULL"},{"name":"command_center_receipts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"command_center_tenant_aliases","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"alias","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"normalized_alias","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'learned'::text","identity":"","not_null":true,"generated":""},{"name":"confidence","type":"double precision","default":"1.0","identity":"","not_null":true,"generated":""},{"name":"use_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"last_used_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"command_center_tenant_aliases_normalized_idx","definition":"CREATE INDEX command_center_tenant_aliases_normalized_idx ON public.command_center_tenant_aliases USING btree (normalized_alias)"},{"name":"command_center_tenant_aliases_pkey","definition":"CREATE UNIQUE INDEX command_center_tenant_aliases_pkey ON public.command_center_tenant_aliases USING btree (id)"},{"name":"command_center_tenant_aliases_tenant_id_normalized_alias_key","definition":"CREATE UNIQUE INDEX command_center_tenant_aliases_tenant_id_normalized_alias_key ON public.command_center_tenant_aliases USING btree (tenant_id, normalized_alias)"}],"policies":[],"triggers":[],"constraints":[{"name":"command_center_tenant_aliases_confidence_check","definition":"CHECK (confidence >= 0::double precision AND confidence <= 1::double precision)"},{"name":"command_center_tenant_aliases_pkey","definition":"PRIMARY KEY (id)"},{"name":"command_center_tenant_aliases_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"command_center_tenant_aliases_tenant_id_normalized_alias_key","definition":"UNIQUE (tenant_id, normalized_alias)"},{"name":"command_center_tenant_aliases_use_count_check","definition":"CHECK (use_count >= 0)"}]},{"table":"communication_compliance_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"result","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"decision","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_response","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"checked_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"checked_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"communication_compliance_events_pkey","definition":"CREATE UNIQUE INDEX communication_compliance_events_pkey ON public.communication_compliance_events USING btree (id)"},{"name":"idx_cce_lead","definition":"CREATE INDEX idx_cce_lead ON public.communication_compliance_events USING btree (lead_id, checked_at DESC)"},{"name":"idx_cce_tenant_phone","definition":"CREATE INDEX idx_cce_tenant_phone ON public.communication_compliance_events USING btree (tenant_org_id, phone_normalized, checked_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"communication_compliance_events","permissive":"PERMISSIVE","policyname":"tenant_members_insert_cce","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"communication_compliance_events","permissive":"PERMISSIVE","policyname":"tenant_members_view_cce","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"communication_compliance_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"communication_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"direction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider","type":"text","default":"'twilio'::text","identity":"","not_null":true,"generated":""},{"name":"provider_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parent_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"homeowner_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"blocked_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcription_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcript_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"disposition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"compliance_disclosure_played","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"consent_logged","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"drop_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"result","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"communication_events_pkey","definition":"CREATE UNIQUE INDEX communication_events_pkey ON public.communication_events USING btree (id)"},{"name":"idx_comm_events_provider_sid","definition":"CREATE INDEX idx_comm_events_provider_sid ON public.communication_events USING btree (tenant_org_id, provider_call_sid) WHERE (provider_call_sid IS NOT NULL)"},{"name":"idx_comm_events_rep","definition":"CREATE INDEX idx_comm_events_rep ON public.communication_events USING btree (rep_id, created_at DESC)"},{"name":"idx_comm_events_rep_today","definition":"CREATE INDEX idx_comm_events_rep_today ON public.communication_events USING btree (rep_id, tenant_org_id, created_at DESC) WHERE (event_type = ANY (ARRAY['call_initiated'::text, 'call_completed'::text, 'call_ended_by_rep'::text, 'outbound_call'::text]))"},{"name":"idx_comm_events_tenant_lead","definition":"CREATE INDEX idx_comm_events_tenant_lead ON public.communication_events USING btree (tenant_org_id, lead_id, created_at DESC)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin()","roles":["public"],"tablename":"communication_events","permissive":"PERMISSIVE","policyname":"comm_events_admin_delete","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_system_admin()","roles":["public"],"tablename":"communication_events","permissive":"PERMISSIVE","policyname":"comm_events_admin_update","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"communication_events","permissive":"PERMISSIVE","policyname":"comm_events_insert_tenant","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"communication_events","permissive":"PERMISSIVE","policyname":"comm_events_select_tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_comm_events_updated_at","definition":"CREATE TRIGGER trg_comm_events_updated_at BEFORE UPDATE ON communication_events FOR EACH ROW EXECUTE FUNCTION set_communication_events_updated_at()"}],"constraints":[{"name":"communication_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"communication_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"communication_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"direction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"communication_log_pkey","definition":"CREATE UNIQUE INDEX communication_log_pkey ON public.communication_log USING btree (id)"},{"name":"idx_comm_log_contact","definition":"CREATE INDEX idx_comm_log_contact ON public.communication_log USING btree (contact_id, created_at DESC)"},{"name":"idx_comm_log_tenant","definition":"CREATE INDEX idx_comm_log_tenant ON public.communication_log USING btree (tenant_org_id, created_at DESC)"},{"name":"idx_comm_log_user","definition":"CREATE INDEX idx_comm_log_user ON public.communication_log USING btree (user_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = communication_log.tenant_org_id) AND (user_roles.role = 'Owner'::app_role))))","roles":["authenticated"],"tablename":"communication_log","permissive":"PERMISSIVE","policyname":"Tenant owners view tenant communication logs","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"communication_log","permissive":"PERMISSIVE","policyname":"Users insert own communication logs","schemaname":"public","with_check":"(user_id = (uid())::text)"},{"cmd":"UPDATE","qual":"(user_id = (uid())::text)","roles":["authenticated"],"tablename":"communication_log","permissive":"PERMISSIVE","policyname":"Users update own communication logs","schemaname":"public","with_check":"(user_id = (uid())::text)"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM unified_contacts\n  WHERE (((unified_contacts.id)::text = communication_log.contact_id) AND ((unified_contacts.assigned_to = (uid())::text) OR (lower(unified_contacts.assigned_to) = lower(( SELECT profiles.email\n           FROM profiles\n          WHERE (profiles.id = uid()))))))))","roles":["authenticated"],"tablename":"communication_log","permissive":"PERMISSIVE","policyname":"Users view assigned contact communication logs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"communication_log","permissive":"PERMISSIVE","policyname":"platform_admin_view_communication_log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"communication_log_communication_type_check","definition":"CHECK (communication_type = ANY (ARRAY['call'::text, 'sms'::text, 'email'::text, 'note'::text]))"},{"name":"communication_log_direction_check","definition":"CHECK (direction = ANY (ARRAY['inbound'::text, 'outbound'::text]))"},{"name":"communication_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"communication_sequence_steps","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"sequence_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"step_order","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"step_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"delay_minutes","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"condition_config","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"task_config","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"communication_sequence_steps_pkey","definition":"CREATE UNIQUE INDEX communication_sequence_steps_pkey ON public.communication_sequence_steps USING btree (id)"},{"name":"idx_sequence_steps_order","definition":"CREATE INDEX idx_sequence_steps_order ON public.communication_sequence_steps USING btree (sequence_id, step_order)"}],"policies":[{"cmd":"ALL","qual":"(sequence_id IN ( SELECT communication_sequences.id\n   FROM communication_sequences\n  WHERE (communication_sequences.tenant_org_id IN ( SELECT user_roles.tenant_id\n           FROM user_roles\n          WHERE (user_roles.user_id = uid())))))","roles":["public"],"tablename":"communication_sequence_steps","permissive":"PERMISSIVE","policyname":"Tenant isolation for sequence_steps","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"communication_sequence_steps_pkey","definition":"PRIMARY KEY (id)"},{"name":"communication_sequence_steps_step_type_check","definition":"CHECK (step_type = ANY (ARRAY['email'::text, 'sms'::text, 'wait'::text, 'condition'::text, 'task'::text]))"}]},{"table":"communication_sequences","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"trigger_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"steps","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"total_enrollments","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"active_enrollments","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"completion_rate","type":"numeric(5,2)","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"communication_sequences_pkey","definition":"CREATE UNIQUE INDEX communication_sequences_pkey ON public.communication_sequences USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"communication_sequences","permissive":"PERMISSIVE","policyname":"Tenant isolation for communication_sequences","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"communication_sequences_pkey","definition":"PRIMARY KEY (id)"},{"name":"communication_sequences_trigger_type_check","definition":"CHECK (trigger_type = ANY (ARRAY['manual'::text, 'status'::text, 'stage'::text, 'event'::text]))"}]},{"table":"communication_setup_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"request_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"requested_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'requested'::text","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"admin_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_by","type":"uuid","default":"uid()","identity":"","not_null":true,"generated":""},{"name":"resolved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"communication_setup_requests_one_active_per_channel","definition":"CREATE UNIQUE INDEX communication_setup_requests_one_active_per_channel ON public.communication_setup_requests USING btree (tenant_id, channel) WHERE (status = ANY (ARRAY['requested'::text, 'in_progress'::text, 'needs_info'::text]))"},{"name":"communication_setup_requests_pkey","definition":"CREATE UNIQUE INDEX communication_setup_requests_pkey ON public.communication_setup_requests USING btree (id)"},{"name":"communication_setup_requests_queue_idx","definition":"CREATE INDEX communication_setup_requests_queue_idx ON public.communication_setup_requests USING btree (status, created_at DESC)"},{"name":"communication_setup_requests_tenant_idx","definition":"CREATE INDEX communication_setup_requests_tenant_idx ON public.communication_setup_requests USING btree (tenant_id, channel, created_at DESC)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin()","roles":["public"],"tablename":"communication_setup_requests","permissive":"PERMISSIVE","policyname":"communication_setup_requests_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"communication_setup_requests","permissive":"PERMISSIVE","policyname":"communication_setup_requests_tenant_insert","schemaname":"public","with_check":"((is_tenant_member(uid(), tenant_id) AND (requested_by = uid()) AND (status = 'requested'::text)) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["public"],"tablename":"communication_setup_requests","permissive":"PERMISSIVE","policyname":"communication_setup_requests_tenant_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["public"],"tablename":"communication_setup_requests","permissive":"PERMISSIVE","policyname":"communication_setup_requests_tenant_update","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())"}],"triggers":[{"name":"communication_setup_requests_guard_update","definition":"CREATE TRIGGER communication_setup_requests_guard_update BEFORE UPDATE ON communication_setup_requests FOR EACH ROW EXECUTE FUNCTION guard_communication_setup_request_update()"}],"constraints":[{"name":"communication_setup_requests_channel_check","definition":"CHECK (channel = ANY (ARRAY['phone'::text, 'email'::text]))"},{"name":"communication_setup_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"communication_setup_requests_request_type_check","definition":"CHECK (request_type = ANY (ARRAY['managed'::text, 'connect_existing'::text]))"},{"name":"communication_setup_requests_status_check","definition":"CHECK (status = ANY (ARRAY['requested'::text, 'in_progress'::text, 'needs_info'::text, 'connected'::text, 'declined'::text]))"},{"name":"communication_setup_requests_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"competitor_sightings","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"territory_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"competitor_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"sighted_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"location","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reported_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"competitor_sightings_pkey","definition":"CREATE UNIQUE INDEX competitor_sightings_pkey ON public.competitor_sightings USING btree (id)"},{"name":"idx_competitor_sightings_territory","definition":"CREATE INDEX idx_competitor_sightings_territory ON public.competitor_sightings USING btree (territory_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = competitor_sightings.tenant_org_id))))","roles":["public"],"tablename":"competitor_sightings","permissive":"PERMISSIVE","policyname":"Tenant members view competitor sightings","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"competitor_sightings","permissive":"PERMISSIVE","policyname":"Users create competitor sightings","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = competitor_sightings.tenant_org_id))))"}],"triggers":[],"constraints":[{"name":"competitor_sightings_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"compliance_audit_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"audit_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"findings","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":"100","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"compliance_audit_runs_pkey","definition":"CREATE UNIQUE INDEX compliance_audit_runs_pkey ON public.compliance_audit_runs USING btree (id)"},{"name":"compliance_audit_runs_unique","definition":"CREATE UNIQUE INDEX compliance_audit_runs_unique ON public.compliance_audit_runs USING btree (audit_date, tenant_org_id)"},{"name":"idx_compliance_audit_tenant_date","definition":"CREATE INDEX idx_compliance_audit_tenant_date ON public.compliance_audit_runs USING btree (tenant_org_id, audit_date DESC)"}],"policies":[{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["authenticated"],"tablename":"compliance_audit_runs","permissive":"PERMISSIVE","policyname":"tenant_members_view_audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"compliance_audit_runs_pkey","definition":"PRIMARY KEY (id)"},{"name":"compliance_audit_runs_score_check","definition":"CHECK (score >= 0 AND score <= 100)"},{"name":"compliance_audit_runs_unique","definition":"UNIQUE (audit_date, tenant_org_id)"}]},{"table":"compliance_provider_settings","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rnd_enabled","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"rnd_provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rnd_block_on_yes","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"rnd_require_override_on_no_data","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"rnd_default_date_strategy","type":"text","default":"'import_date'::text","identity":"","not_null":true,"generated":""},{"name":"litigator_suppression_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"frequency_cap_max_attempts","type":"integer","default":"3","identity":"","not_null":true,"generated":""},{"name":"frequency_cap_window_days","type":"integer","default":"30","identity":"","not_null":true,"generated":""},{"name":"frequency_cap_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"recording_disclosure_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"recording_disclosure_text","type":"text","default":"'This call may be recorded for quality and compliance.'::text","identity":"","not_null":true,"generated":""},{"name":"florida_dnc_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"compliance_provider_settings_pkey","definition":"CREATE UNIQUE INDEX compliance_provider_settings_pkey ON public.compliance_provider_settings USING btree (id)"},{"name":"compliance_provider_settings_tenant_org_id_key","definition":"CREATE UNIQUE INDEX compliance_provider_settings_tenant_org_id_key ON public.compliance_provider_settings USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"compliance_provider_settings","permissive":"PERMISSIVE","policyname":"tenant_members_view_compliance_settings","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) AND (is_system_admin() OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = compliance_provider_settings.tenant_org_id) AND (ur.role = ANY (ARRAY['Tenant Owner'::app_role, 'Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))))","roles":["authenticated"],"tablename":"compliance_provider_settings","permissive":"PERMISSIVE","policyname":"tenant_owners_manage_compliance_settings","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"}],"triggers":[{"name":"trg_compliance_settings_updated_at","definition":"CREATE TRIGGER trg_compliance_settings_updated_at BEFORE UPDATE ON compliance_provider_settings FOR EACH ROW EXECUTE FUNCTION touch_compliance_settings_updated_at()"}],"constraints":[{"name":"compliance_provider_settings_pkey","definition":"PRIMARY KEY (id)"},{"name":"compliance_provider_settings_tenant_org_id_key","definition":"UNIQUE (tenant_org_id)"}]},{"table":"compliance_test_numbers","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"added_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"compliance_test_numbers_pkey","definition":"CREATE UNIQUE INDEX compliance_test_numbers_pkey ON public.compliance_test_numbers USING btree (id)"},{"name":"compliance_test_numbers_tenant_org_id_phone_normalized_key","definition":"CREATE UNIQUE INDEX compliance_test_numbers_tenant_org_id_phone_normalized_key ON public.compliance_test_numbers USING btree (tenant_org_id, phone_normalized)"},{"name":"idx_compliance_test_numbers_phone","definition":"CREATE INDEX idx_compliance_test_numbers_phone ON public.compliance_test_numbers USING btree (phone_normalized)"}],"policies":[{"cmd":"DELETE","qual":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_owner_for(uid(), tenant_org_id)))","roles":["authenticated"],"tablename":"compliance_test_numbers","permissive":"PERMISSIVE","policyname":"test_numbers_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"compliance_test_numbers","permissive":"PERMISSIVE","policyname":"test_numbers_insert","schemaname":"public","with_check":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_owner_for(uid(), tenant_org_id)))"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"compliance_test_numbers","permissive":"PERMISSIVE","policyname":"test_numbers_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"compliance_test_numbers_pkey","definition":"PRIMARY KEY (id)"},{"name":"compliance_test_numbers_tenant_org_id_phone_normalized_key","definition":"UNIQUE (tenant_org_id, phone_normalized)"}]},{"table":"compliance_violations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"violation_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"attempted_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"details","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"acknowledged_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"compliance_violations_pkey","definition":"CREATE UNIQUE INDEX compliance_violations_pkey ON public.compliance_violations USING btree (id)"},{"name":"idx_compliance_violations_tenant","definition":"CREATE INDEX idx_compliance_violations_tenant ON public.compliance_violations USING btree (tenant_id, created_at DESC)"},{"name":"idx_compliance_violations_user","definition":"CREATE INDEX idx_compliance_violations_user ON public.compliance_violations USING btree (user_id, created_at DESC)"}],"policies":[{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR ((tenant_id IS NOT NULL) AND has_role(uid(), tenant_id, 'Owner'::app_role)))","roles":["authenticated"],"tablename":"compliance_violations","permissive":"PERMISSIVE","policyname":"Acknowledge violations: admins and owners","schemaname":"public","with_check":"(is_system_admin(uid()) OR ((tenant_id IS NOT NULL) AND has_role(uid(), tenant_id, 'Owner'::app_role)))"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"compliance_violations","permissive":"PERMISSIVE","policyname":"Users log their own violations","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (uid() = user_id) OR ((tenant_id IS NOT NULL) AND has_role(uid(), tenant_id, 'Owner'::app_role)))","roles":["authenticated"],"tablename":"compliance_violations","permissive":"PERMISSIVE","policyname":"View violations: admins, owners, self","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"compliance_violations_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"comprehensive_audit_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_category","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"resource_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resource_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resource_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"old_value","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_value","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"session_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"request_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"success","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"severity","type":"text","default":"'info'::text","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"human_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_fields","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"comprehensive_audit_logs_pkey","definition":"CREATE UNIQUE INDEX comprehensive_audit_logs_pkey ON public.comprehensive_audit_logs USING btree (id)"},{"name":"idx_comprehensive_audit_event_category","definition":"CREATE INDEX idx_comprehensive_audit_event_category ON public.comprehensive_audit_logs USING btree (event_category)"},{"name":"idx_comprehensive_audit_event_type","definition":"CREATE INDEX idx_comprehensive_audit_event_type ON public.comprehensive_audit_logs USING btree (event_type)"},{"name":"idx_comprehensive_audit_resource","definition":"CREATE INDEX idx_comprehensive_audit_resource ON public.comprehensive_audit_logs USING btree (resource_type, resource_id)"},{"name":"idx_comprehensive_audit_severity","definition":"CREATE INDEX idx_comprehensive_audit_severity ON public.comprehensive_audit_logs USING btree (severity) WHERE (severity = ANY (ARRAY['warn'::text, 'error'::text, 'critical'::text]))"},{"name":"idx_comprehensive_audit_tenant","definition":"CREATE INDEX idx_comprehensive_audit_tenant ON public.comprehensive_audit_logs USING btree (tenant_id)"},{"name":"idx_comprehensive_audit_timestamp","definition":"CREATE INDEX idx_comprehensive_audit_timestamp ON public.comprehensive_audit_logs USING btree (\"timestamp\" DESC)"},{"name":"idx_comprehensive_audit_user","definition":"CREATE INDEX idx_comprehensive_audit_user ON public.comprehensive_audit_logs USING btree (user_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"comprehensive_audit_logs","permissive":"PERMISSIVE","policyname":"godmode_full_access_audit","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role])))))","roles":["authenticated"],"tablename":"comprehensive_audit_logs","permissive":"PERMISSIVE","policyname":"tenant_admins_view_audit","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"comprehensive_audit_logs","permissive":"PERMISSIVE","policyname":"users_view_own_audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"comprehensive_audit_logs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"config_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"config_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"old_value","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_value","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"config_history_pkey","definition":"CREATE UNIQUE INDEX config_history_pkey ON public.config_history USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"config_history","permissive":"PERMISSIVE","policyname":"platform_admin_view_config_history","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"config_history_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"consent_ledger","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"consent_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"consent_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"capture_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signature_artifact_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"granted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revocation_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"captured_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"consent_ledger_pkey","definition":"CREATE UNIQUE INDEX consent_ledger_pkey ON public.consent_ledger USING btree (id)"},{"name":"idx_consent_lead","definition":"CREATE INDEX idx_consent_lead ON public.consent_ledger USING btree (lead_id)"},{"name":"idx_consent_tenant_phone","definition":"CREATE INDEX idx_consent_tenant_phone ON public.consent_ledger USING btree (tenant_org_id, phone_normalized, granted_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"consent_ledger","permissive":"PERMISSIVE","policyname":"tenant_members_insert_consent","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"consent_ledger","permissive":"PERMISSIVE","policyname":"tenant_members_update_consent","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"consent_ledger","permissive":"PERMISSIVE","policyname":"tenant_members_view_consent","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"consent_ledger_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"contact_assignments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assignment_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"can_edit","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"can_view_notes","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"assigned_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_assignments_contact_id_user_id_tenant_id_key","definition":"CREATE UNIQUE INDEX contact_assignments_contact_id_user_id_tenant_id_key ON public.contact_assignments USING btree (contact_id, user_id, tenant_id)"},{"name":"contact_assignments_pkey","definition":"CREATE UNIQUE INDEX contact_assignments_pkey ON public.contact_assignments USING btree (id)"},{"name":"idx_contact_assignments_contact","definition":"CREATE INDEX idx_contact_assignments_contact ON public.contact_assignments USING btree (contact_id)"},{"name":"idx_contact_assignments_tenant","definition":"CREATE INDEX idx_contact_assignments_tenant ON public.contact_assignments USING btree (tenant_id)"},{"name":"idx_contact_assignments_user","definition":"CREATE INDEX idx_contact_assignments_user ON public.contact_assignments USING btree (user_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"contact_assignments","permissive":"PERMISSIVE","policyname":"Users create contact assignments","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN unified_contacts uc ON ((uc.tenant_org_id = (ur.tenant_id)::text)))\n  WHERE ((ur.user_id = uid()) AND (uc.id = contact_assignments.contact_id)))) OR is_system_admin(uid()))"},{"cmd":"DELETE","qual":"((assigned_by = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = contact_assignments.tenant_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["public"],"tablename":"contact_assignments","permissive":"PERMISSIVE","policyname":"Users delete contact assignments","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((assigned_by = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = contact_assignments.tenant_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["public"],"tablename":"contact_assignments","permissive":"PERMISSIVE","policyname":"Users update contact assignments","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND (contact_assignments.tenant_id = ur.tenant_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["public"],"tablename":"contact_assignments","permissive":"PERMISSIVE","policyname":"Users view contact assignments","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"contact_assignments_contact_id_user_id_tenant_id_key","definition":"UNIQUE (contact_id, user_id, tenant_id)"},{"name":"contact_assignments_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"contact_claims","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"slot_number","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"date_of_loss","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_type","type":"text","default":"'Other'::text","identity":"","not_null":false,"generated":""},{"name":"claim_status","type":"text","default":"'Open'::text","identity":"","not_null":false,"generated":""},{"name":"adjuster_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"deductible","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"coverage_a","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"settlement_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"fee_percentage","type":"numeric(5,2)","default":"10.00","identity":"","not_null":false,"generated":""},{"name":"fee_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"fee_status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"settlement_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"referral_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referral_partner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_issued_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_issued_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_issued_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_issued_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_issued_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_received_by_homeowner_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_received_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_pipeline_status","type":"payment_pipeline_status","default":null,"identity":"","not_null":false,"generated":""},{"name":"cause_of_loss","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"representation_agreement_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pa_inspection_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier_inspection_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimate_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"pa_estimate_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_status","type":"claim_payment_lifecycle_v4","default":"'claim_not_started'::claim_payment_lifecycle_v4","identity":"","not_null":true,"generated":""},{"name":"claim_payment_status_updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_status_updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_effective_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_expiration_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"coverage_b","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"coverage_c","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"coverage_d","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"mortgage_company","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"loss_cause","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_filed_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier_acknowledged_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"inspection_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier_offer_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"pa_demand_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"prior_pa_or_attorney_involved","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"homeowner_occupied","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"damage_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"interior_damage","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"exterior_damage","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_damage","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"water_damage","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"emergency_mitigation_done","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"best_contact_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"preferred_contact_time","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"expected_fee_amount","type":"numeric","default":"\nCASE\n    WHEN ((settlement_amount IS NOT NULL) AND (fee_percentage IS NOT NULL)) THEN round(((settlement_amount * fee_percentage) / 100.0), 2)\n    ELSE NULL::numeric\nEND","identity":"","not_null":false,"generated":"s"},{"name":"next_action","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"call_disposition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"consultation_requested","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"last_call_captured_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_call_captured_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_stage","type":"text","default":"'P1_INTRO'::text","identity":"","not_null":true,"generated":""},{"name":"canonical_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_claims_pkey","definition":"CREATE UNIQUE INDEX contact_claims_pkey ON public.contact_claims USING btree (id)"},{"name":"contact_claims_unique_slot","definition":"CREATE UNIQUE INDEX contact_claims_unique_slot ON public.contact_claims USING btree (contact_id, tenant_org_id, slot_number)"},{"name":"idx_contact_claims_cause","definition":"CREATE INDEX idx_contact_claims_cause ON public.contact_claims USING btree (tenant_org_id, cause_of_loss)"},{"name":"idx_contact_claims_contact","definition":"CREATE INDEX idx_contact_claims_contact ON public.contact_claims USING btree (contact_id, tenant_org_id)"},{"name":"idx_contact_claims_fee_status","definition":"CREATE INDEX idx_contact_claims_fee_status ON public.contact_claims USING btree (fee_status) WHERE (fee_status IS NOT NULL)"},{"name":"idx_contact_claims_rep_status","definition":"CREATE INDEX idx_contact_claims_rep_status ON public.contact_claims USING btree (tenant_org_id, representation_agreement_status)"},{"name":"idx_contact_claims_tenant","definition":"CREATE INDEX idx_contact_claims_tenant ON public.contact_claims USING btree (tenant_org_id)"},{"name":"idx_contact_claims_tenant_stage","definition":"CREATE INDEX idx_contact_claims_tenant_stage ON public.contact_claims USING btree (tenant_org_id, claim_stage)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"contact_claims","permissive":"PERMISSIVE","policyname":"Tenant members can create claims","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"contact_claims","permissive":"PERMISSIVE","policyname":"Tenant members can delete claims","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"contact_claims","permissive":"PERMISSIVE","policyname":"Tenant members can update claims","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"contact_claims","permissive":"PERMISSIVE","policyname":"Tenant members can view claims","schemaname":"public","with_check":null}],"triggers":[{"name":"revoke_customer_portal_when_claims_close","definition":"CREATE TRIGGER revoke_customer_portal_when_claims_close AFTER DELETE OR UPDATE OF claim_stage ON contact_claims FOR EACH ROW EXECUTE FUNCTION revoke_customer_portal_when_claims_close()"},{"name":"trg_auto_stamp_claim_check_issued","definition":"CREATE TRIGGER trg_auto_stamp_claim_check_issued BEFORE INSERT OR UPDATE OF settlement_amount, settlement_date ON contact_claims FOR EACH ROW EXECUTE FUNCTION auto_stamp_claim_check_issued()"},{"name":"trg_dispatch_homeowner_update_on_claim_stage","definition":"CREATE TRIGGER trg_dispatch_homeowner_update_on_claim_stage AFTER UPDATE OF claim_status ON contact_claims FOR EACH ROW EXECUTE FUNCTION dispatch_homeowner_claim_stage_update()"},{"name":"trg_run_pa_claim_automation_rules","definition":"CREATE TRIGGER trg_run_pa_claim_automation_rules AFTER UPDATE OF claim_stage ON contact_claims FOR EACH ROW WHEN (old.claim_stage IS DISTINCT FROM new.claim_stage) EXECUTE FUNCTION run_pa_claim_automation_rules()"},{"name":"trg_seed_statutory_deadlines","definition":"CREATE TRIGGER trg_seed_statutory_deadlines AFTER INSERT ON contact_claims FOR EACH ROW EXECUTE FUNCTION seed_statutory_deadlines()"},{"name":"update_contact_claims_updated_at","definition":"CREATE TRIGGER update_contact_claims_updated_at BEFORE UPDATE ON contact_claims FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"contact_claims_canonical_contact_fkey","definition":"FOREIGN KEY (canonical_contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"contact_claims_claim_stage_check","definition":"CHECK (claim_stage = ANY (ARRAY['P1_INTRO'::text, 'P2_SCREEN'::text, 'P3_SIGN'::text, 'P4_SCHEDULE'::text, 'P5_DOCS'::text, 'P6_NEGOTIATE'::text, 'P7_CLOSE'::text]))"},{"name":"contact_claims_pkey","definition":"PRIMARY KEY (id)"},{"name":"contact_claims_slot_check","definition":"CHECK (slot_number >= 1)"},{"name":"contact_claims_unique_slot","definition":"UNIQUE (contact_id, tenant_org_id, slot_number)"}]},{"table":"contact_communication_preferences","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"email_enabled","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"sms_enabled","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"call_enabled","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"preferred_channel","type":"text","default":"'email'::text","identity":"","not_null":false,"generated":""},{"name":"preferred_time_start","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"preferred_time_end","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"timezone","type":"text","default":"'America/New_York'::text","identity":"","not_null":false,"generated":""},{"name":"do_not_contact_until","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_communication_preferences_pkey","definition":"CREATE UNIQUE INDEX contact_communication_preferences_pkey ON public.contact_communication_preferences USING btree (id)"},{"name":"contact_communication_preferences_tenant_id_contact_id_key","definition":"CREATE UNIQUE INDEX contact_communication_preferences_tenant_id_contact_id_key ON public.contact_communication_preferences USING btree (tenant_id, contact_id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"contact_communication_preferences","permissive":"PERMISSIVE","policyname":"Tenant isolation for contact_preferences","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"contact_communication_preferences_pkey","definition":"PRIMARY KEY (id)"},{"name":"contact_communication_preferences_tenant_id_contact_id_key","definition":"UNIQUE (tenant_id, contact_id)"}]},{"table":"contact_files","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_size","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"mime_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"public_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"extracted_metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"drive_file_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_sync_status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"drive_synced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"folder","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tags","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_files_pkey","definition":"CREATE UNIQUE INDEX contact_files_pkey ON public.contact_files USING btree (id)"},{"name":"idx_contact_files_archived","definition":"CREATE INDEX idx_contact_files_archived ON public.contact_files USING btree (tenant_org_id, archived_at)"},{"name":"idx_contact_files_claim","definition":"CREATE INDEX idx_contact_files_claim ON public.contact_files USING btree (claim_id)"},{"name":"idx_contact_files_contact_id","definition":"CREATE INDEX idx_contact_files_contact_id ON public.contact_files USING btree (contact_id)"},{"name":"idx_contact_files_created_at","definition":"CREATE INDEX idx_contact_files_created_at ON public.contact_files USING btree (created_at DESC)"},{"name":"idx_contact_files_drive_file_id","definition":"CREATE INDEX idx_contact_files_drive_file_id ON public.contact_files USING btree (drive_file_id) WHERE (drive_file_id IS NOT NULL)"},{"name":"idx_contact_files_drive_sync_status","definition":"CREATE INDEX idx_contact_files_drive_sync_status ON public.contact_files USING btree (drive_sync_status)"},{"name":"idx_contact_files_folder","definition":"CREATE INDEX idx_contact_files_folder ON public.contact_files USING btree (tenant_org_id, folder) WHERE (folder IS NOT NULL)"},{"name":"idx_contact_files_tags","definition":"CREATE INDEX idx_contact_files_tags ON public.contact_files USING gin (tags)"},{"name":"idx_contact_files_tenant_org_id","definition":"CREATE INDEX idx_contact_files_tenant_org_id ON public.contact_files USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"contact_files","permissive":"PERMISSIVE","policyname":"Users can delete files for their tenant","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"contact_files","permissive":"PERMISSIVE","policyname":"Users can insert files for their tenant","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"contact_files","permissive":"PERMISSIVE","policyname":"Users can update files for their tenant","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"contact_files","permissive":"PERMISSIVE","policyname":"Users can view files for their tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"audit_trigger_contact_files","definition":"CREATE TRIGGER audit_trigger_contact_files AFTER INSERT OR DELETE OR UPDATE ON contact_files FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"}],"constraints":[{"name":"contact_files_file_type_check","definition":"CHECK (file_type = ANY (ARRAY['doc'::text, 'photo'::text, 'audio'::text, 'video'::text, 'document'::text, 'other'::text]))"},{"name":"contact_files_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"contact_links","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"link_group_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_origin","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"contact_links_contact_id_tenant_id_key","definition":"CREATE UNIQUE INDEX contact_links_contact_id_tenant_id_key ON public.contact_links USING btree (contact_id, tenant_id)"},{"name":"contact_links_pkey","definition":"CREATE UNIQUE INDEX contact_links_pkey ON public.contact_links USING btree (id)"},{"name":"idx_contact_links_contact","definition":"CREATE INDEX idx_contact_links_contact ON public.contact_links USING btree (contact_id)"},{"name":"idx_contact_links_group","definition":"CREATE INDEX idx_contact_links_group ON public.contact_links USING btree (link_group_id)"},{"name":"idx_contact_links_tenant","definition":"CREATE INDEX idx_contact_links_tenant ON public.contact_links USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"contact_links","permissive":"PERMISSIVE","policyname":"System admins can manage contact links","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_tenant_member((tenant_id)::text)","roles":["authenticated"],"tablename":"contact_links","permissive":"PERMISSIVE","policyname":"Tenant members can view their contact links","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(link_group_id IN ( SELECT get_user_link_group_ids() AS get_user_link_group_ids))","roles":["authenticated"],"tablename":"contact_links","permissive":"PERMISSIVE","policyname":"Users can view linked group members","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"contact_links_contact_id_tenant_id_key","definition":"UNIQUE (contact_id, tenant_id)"},{"name":"contact_links_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"contact_note_revisions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"note_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"previous_content","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"edited_by_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"edited_by_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"contact_note_revisions_pkey","definition":"CREATE UNIQUE INDEX contact_note_revisions_pkey ON public.contact_note_revisions USING btree (id)"},{"name":"idx_note_revisions_note","definition":"CREATE INDEX idx_note_revisions_note ON public.contact_note_revisions USING btree (note_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"contact_note_revisions","permissive":"PERMISSIVE","policyname":"Authenticated users can insert revisions","schemaname":"public","with_check":"(edited_by_id = uid())"},{"cmd":"SELECT","qual":"(note_id IN ( SELECT cn.id\n   FROM contact_notes cn\n  WHERE (cn.tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n           FROM security_active_user_tenant_memberships user_tenant_memberships\n          WHERE (user_tenant_memberships.user_id = uid())))))","roles":["authenticated"],"tablename":"contact_note_revisions","permissive":"PERMISSIVE","policyname":"Tenant members can view revisions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"contact_note_revisions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"contact_notes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"note_type","type":"text","default":"'general'::text","identity":"","not_null":true,"generated":""},{"name":"content","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_notes_pkey","definition":"CREATE UNIQUE INDEX contact_notes_pkey ON public.contact_notes USING btree (id)"},{"name":"idx_contact_notes_claim","definition":"CREATE INDEX idx_contact_notes_claim ON public.contact_notes USING btree (claim_id)"},{"name":"idx_contact_notes_contact","definition":"CREATE INDEX idx_contact_notes_contact ON public.contact_notes USING btree (contact_id)"},{"name":"idx_contact_notes_tenant","definition":"CREATE INDEX idx_contact_notes_tenant ON public.contact_notes USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"is_admin_or_higher(tenant_org_id, uid())","roles":["authenticated"],"tablename":"contact_notes","permissive":"PERMISSIVE","policyname":"Admins and owners can delete notes","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"contact_notes","permissive":"PERMISSIVE","policyname":"Authenticated users can insert notes","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) AND (user_id = uid()))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["authenticated"],"tablename":"contact_notes","permissive":"PERMISSIVE","policyname":"Tenant members can view notes","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"contact_notes","permissive":"PERMISSIVE","policyname":"Users can edit own notes","schemaname":"public","with_check":"(user_id = uid())"}],"triggers":[],"constraints":[{"name":"contact_notes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"contact_photos","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phase","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tags","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"drive_file_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_sync_status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"drive_synced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"slope","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"exif_lat","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"exif_lng","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"exif_taken_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_slope","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_slope_confidence","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"damage_indicators","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"damage_severity","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_analyzed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_photos_pkey","definition":"CREATE UNIQUE INDEX contact_photos_pkey ON public.contact_photos USING btree (id)"},{"name":"idx_contact_photos_claim","definition":"CREATE INDEX idx_contact_photos_claim ON public.contact_photos USING btree (claim_id)"},{"name":"idx_contact_photos_contact","definition":"CREATE INDEX idx_contact_photos_contact ON public.contact_photos USING btree (contact_id)"},{"name":"idx_contact_photos_contact_id","definition":"CREATE INDEX idx_contact_photos_contact_id ON public.contact_photos USING btree (contact_id)"},{"name":"idx_contact_photos_contact_slope","definition":"CREATE INDEX idx_contact_photos_contact_slope ON public.contact_photos USING btree (contact_id, roof_slope)"},{"name":"idx_contact_photos_drive_file_id","definition":"CREATE INDEX idx_contact_photos_drive_file_id ON public.contact_photos USING btree (drive_file_id) WHERE (drive_file_id IS NOT NULL)"},{"name":"idx_contact_photos_drive_sync_status","definition":"CREATE INDEX idx_contact_photos_drive_sync_status ON public.contact_photos USING btree (drive_sync_status)"},{"name":"idx_contact_photos_slope","definition":"CREATE INDEX idx_contact_photos_slope ON public.contact_photos USING btree (contact_id, slope)"},{"name":"idx_contact_photos_status","definition":"CREATE INDEX idx_contact_photos_status ON public.contact_photos USING btree (status)"},{"name":"idx_contact_photos_tenant","definition":"CREATE INDEX idx_contact_photos_tenant ON public.contact_photos USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (contact_photos.tenant_org_id)::uuid) AND (user_roles.role = ANY (ARRAY['Admin'::app_role, 'GodMode'::app_role, 'Owner'::app_role])))))","roles":["public"],"tablename":"contact_photos","permissive":"PERMISSIVE","policyname":"Admins can delete photos","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"contact_photos","permissive":"PERMISSIVE","policyname":"Users can insert photos in their tenant","schemaname":"public","with_check":"((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"UPDATE","qual":"(created_by = uid())","roles":["public"],"tablename":"contact_photos","permissive":"PERMISSIVE","policyname":"Users can update their own photos","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"contact_photos","permissive":"PERMISSIVE","policyname":"Users can view photos in their tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"audit_trigger_contact_photos","definition":"CREATE TRIGGER audit_trigger_contact_photos AFTER INSERT OR DELETE OR UPDATE ON contact_photos FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"},{"name":"update_contact_photos_updated_at","definition":"CREATE TRIGGER update_contact_photos_updated_at BEFORE UPDATE ON contact_photos FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"contact_photos_damage_severity_chk","definition":"CHECK (damage_severity IS NULL OR (damage_severity = ANY (ARRAY['low'::text, 'medium'::text, 'high'::text])))"},{"name":"contact_photos_phase_check","definition":"CHECK (phase = ANY (ARRAY['before'::text, 'after'::text, 'general'::text]))"},{"name":"contact_photos_pkey","definition":"PRIMARY KEY (id)"},{"name":"contact_photos_roof_slope_chk","definition":"CHECK (roof_slope IS NULL OR (roof_slope = ANY (ARRAY['north'::text, 'south'::text, 'east'::text, 'west'::text, 'northeast'::text, 'northwest'::text, 'southeast'::text, 'southwest'::text, 'ridge'::text, 'valley'::text, 'eave'::text, 'penetration'::text, 'overview'::text, 'unknown'::text])))"},{"name":"contact_photos_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'ready'::text, 'failed'::text]))"}]},{"table":"contact_tenant_memberships","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_rep","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_user","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"jobs_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"graduated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_date","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_time","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes2","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes3","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes4","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"additional_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"quality_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_tags","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_claim_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimate_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"work_classification","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"salesperson_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_touched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_contact","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"deletion_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"service_scopes","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"agreement_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_document_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_resolver_status","type":"text","default":"'unresolved'::text","identity":"","not_null":true,"generated":""},{"name":"agreement_resolver_confidence","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_resolver_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_resolver_confirmed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_resolver_confirmed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"contact_tenant_memberships_contact_id_tenant_id_key","definition":"CREATE UNIQUE INDEX contact_tenant_memberships_contact_id_tenant_id_key ON public.contact_tenant_memberships USING btree (contact_id, tenant_id)"},{"name":"contact_tenant_memberships_pkey","definition":"CREATE UNIQUE INDEX contact_tenant_memberships_pkey ON public.contact_tenant_memberships USING btree (id)"},{"name":"idx_ctm_assigned_to","definition":"CREATE INDEX idx_ctm_assigned_to ON public.contact_tenant_memberships USING btree (assigned_to)"},{"name":"idx_ctm_contact_id","definition":"CREATE INDEX idx_ctm_contact_id ON public.contact_tenant_memberships USING btree (contact_id)"},{"name":"idx_ctm_deleted_at","definition":"CREATE INDEX idx_ctm_deleted_at ON public.contact_tenant_memberships USING btree (deleted_at)"},{"name":"idx_ctm_lead_id","definition":"CREATE INDEX idx_ctm_lead_id ON public.contact_tenant_memberships USING btree (lead_id)"},{"name":"idx_ctm_tenant_id","definition":"CREATE INDEX idx_ctm_tenant_id ON public.contact_tenant_memberships USING btree (tenant_id)"},{"name":"idx_ctm_tenant_status","definition":"CREATE INDEX idx_ctm_tenant_status ON public.contact_tenant_memberships USING btree (tenant_id, status) WHERE (deleted_at IS NULL)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member((tenant_id)::text)","roles":["authenticated"],"tablename":"contact_tenant_memberships","permissive":"PERMISSIVE","policyname":"ctm_delete_own_tenant","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"contact_tenant_memberships","permissive":"PERMISSIVE","policyname":"ctm_insert_own_tenant","schemaname":"public","with_check":"is_tenant_member((tenant_id)::text)"},{"cmd":"SELECT","qual":"is_tenant_member((tenant_id)::text)","roles":["authenticated"],"tablename":"contact_tenant_memberships","permissive":"PERMISSIVE","policyname":"ctm_select_own_tenant","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member((tenant_id)::text)","roles":["authenticated"],"tablename":"contact_tenant_memberships","permissive":"PERMISSIVE","policyname":"ctm_update_own_tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"update_ctm_updated_at","definition":"CREATE TRIGGER update_ctm_updated_at BEFORE UPDATE ON contact_tenant_memberships FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"contact_tenant_memberships_contact_id_tenant_id_key","definition":"UNIQUE (contact_id, tenant_id)"},{"name":"contact_tenant_memberships_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"conversion_funnels","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"character varying(255)","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"stages","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"conversion_funnels_pkey","definition":"CREATE UNIQUE INDEX conversion_funnels_pkey ON public.conversion_funnels USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"conversion_funnels","permissive":"PERMISSIVE","policyname":"Users can manage funnels","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"conversion_funnels","permissive":"PERMISSIVE","policyname":"Users can view own tenant funnels","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"conversion_funnels_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"cross_tenant_assignment_backfill_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_tenant","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"prior_assigned_user","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"prior_assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_tenant","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"cleared_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"cross_tenant_assignment_backfill_log_pkey","definition":"CREATE UNIQUE INDEX cross_tenant_assignment_backfill_log_pkey ON public.cross_tenant_assignment_backfill_log USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"cross_tenant_assignment_backfill_log","permissive":"PERMISSIVE","policyname":"system admins can read backfill log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"cross_tenant_assignment_backfill_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"custom_field_values","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"custom_field_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"entity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"custom_field_values_custom_field_id_entity_id_key","definition":"CREATE UNIQUE INDEX custom_field_values_custom_field_id_entity_id_key ON public.custom_field_values USING btree (custom_field_id, entity_id)"},{"name":"custom_field_values_pkey","definition":"CREATE UNIQUE INDEX custom_field_values_pkey ON public.custom_field_values USING btree (id)"},{"name":"idx_custom_field_values_custom_field_id","definition":"CREATE INDEX idx_custom_field_values_custom_field_id ON public.custom_field_values USING btree (custom_field_id)"},{"name":"idx_custom_field_values_entity","definition":"CREATE INDEX idx_custom_field_values_entity ON public.custom_field_values USING btree (entity_type, entity_id)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = custom_field_values.tenant_id))))","roles":["public"],"tablename":"custom_field_values","permissive":"PERMISSIVE","policyname":"Users manage custom values","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = custom_field_values.tenant_id))))","roles":["public"],"tablename":"custom_field_values","permissive":"PERMISSIVE","policyname":"Users view tenant custom values","schemaname":"public","with_check":null}],"triggers":[{"name":"custom_field_values_updated_at","definition":"CREATE TRIGGER custom_field_values_updated_at BEFORE UPDATE ON custom_field_values FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"custom_field_values_custom_field_id_entity_id_key","definition":"UNIQUE (custom_field_id, entity_id)"},{"name":"custom_field_values_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"custom_fields","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"field_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"field_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"field_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"options","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_required","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"display_order","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"custom_fields_pkey","definition":"CREATE UNIQUE INDEX custom_fields_pkey ON public.custom_fields USING btree (id)"},{"name":"custom_fields_tenant_id_entity_type_field_name_key","definition":"CREATE UNIQUE INDEX custom_fields_tenant_id_entity_type_field_name_key ON public.custom_fields USING btree (tenant_id, entity_type, field_name)"},{"name":"idx_custom_fields_entity_type","definition":"CREATE INDEX idx_custom_fields_entity_type ON public.custom_fields USING btree (entity_type)"},{"name":"idx_custom_fields_tenant_id","definition":"CREATE INDEX idx_custom_fields_tenant_id ON public.custom_fields USING btree (tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = custom_fields.tenant_id))))","roles":["public"],"tablename":"custom_fields","permissive":"PERMISSIVE","policyname":"Users view tenant custom fields","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"custom_fields","permissive":"PERMISSIVE","policyname":"custom_fields_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_id IS NULL) OR is_tenant_member(uid(), (tenant_id)::uuid))","roles":["public"],"tablename":"custom_fields","permissive":"PERMISSIVE","policyname":"custom_fields_tenant_member_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_id)::uuid))","roles":["public"],"tablename":"custom_fields","permissive":"PERMISSIVE","policyname":"custom_fields_tenant_owner_manage","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_id)::uuid))"}],"triggers":[{"name":"custom_fields_updated_at","definition":"CREATE TRIGGER custom_fields_updated_at BEFORE UPDATE ON custom_fields FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"custom_fields_pkey","definition":"PRIMARY KEY (id)"},{"name":"custom_fields_tenant_id_entity_type_field_name_key","definition":"UNIQUE (tenant_id, entity_type, field_name)"}]},{"table":"customer_leads","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"damage_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_company","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'New'::text","identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"customer_leads_pkey","definition":"CREATE UNIQUE INDEX customer_leads_pkey ON public.customer_leads USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"Public can submit customer_leads with valid name","schemaname":"public","with_check":"((name IS NOT NULL) AND (length(TRIM(BOTH FROM name)) > 0))"},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"Public can submit leads with valid name","schemaname":"public","with_check":"((name IS NOT NULL) AND (length(TRIM(BOTH FROM name)) > 0))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"cl_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"cl_update","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (customer_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"tenant_users_delete_customer_leads","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"tenant_users_insert_customer_leads","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (customer_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (customer_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"tenant_users_update_customer_leads","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (customer_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (customer_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"customer_leads","permissive":"PERMISSIVE","policyname":"tenant_users_view_customer_leads","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"customer_leads_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"customer_portal_access","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"access_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"last_login_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"customer_portal_access_access_token_key","definition":"CREATE UNIQUE INDEX customer_portal_access_access_token_key ON public.customer_portal_access USING btree (access_token)"},{"name":"customer_portal_access_claim_scope_idx","definition":"CREATE INDEX customer_portal_access_claim_scope_idx ON public.customer_portal_access USING btree (tenant_id, contact_id, claim_id) WHERE (claim_id IS NOT NULL)"},{"name":"customer_portal_access_contact_id_key","definition":"CREATE UNIQUE INDEX customer_portal_access_contact_id_key ON public.customer_portal_access USING btree (contact_id)"},{"name":"customer_portal_access_pkey","definition":"CREATE UNIQUE INDEX customer_portal_access_pkey ON public.customer_portal_access USING btree (id)"},{"name":"customer_portal_access_token_hash_key","definition":"CREATE UNIQUE INDEX customer_portal_access_token_hash_key ON public.customer_portal_access USING btree (token_hash) WHERE (token_hash IS NOT NULL)"},{"name":"idx_customer_portal_access_token","definition":"CREATE INDEX idx_customer_portal_access_token ON public.customer_portal_access USING btree (access_token)"},{"name":"idx_customer_portal_contact_id","definition":"CREATE INDEX idx_customer_portal_contact_id ON public.customer_portal_access USING btree (contact_id)"},{"name":"idx_portal_access_token_hash","definition":"CREATE INDEX idx_portal_access_token_hash ON public.customer_portal_access USING btree (token_hash)"}],"policies":[{"cmd":"SELECT","qual":"((email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text) OR ((is_active = true) AND (access_token IN ( SELECT unnest(string_to_array(((current_setting('request.headers'::text, true))::json ->> 'x-portal-token'::text), ','::text)) AS unnest))))","roles":["public"],"tablename":"customer_portal_access","permissive":"PERMISSIVE","policyname":"Customers can access own portal records","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_system_admin(uid()) OR is_admin_or_higher(uid(), (tenant_id)::uuid))","roles":["authenticated"],"tablename":"customer_portal_access","permissive":"PERMISSIVE","policyname":"Tenant admins manage portal access","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"customer_portal_access_access_token_key","definition":"UNIQUE (access_token)"},{"name":"customer_portal_access_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dashboard_widgets","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"widget_type","type":"character varying(50)","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"character varying(255)","default":null,"identity":"","not_null":true,"generated":""},{"name":"config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"position","type":"jsonb","default":"'{\"h\": 3, \"w\": 4, \"x\": 0, \"y\": 0}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_visible","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"refresh_interval","type":"integer","default":"300","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"dashboard_widgets_pkey","definition":"CREATE UNIQUE INDEX dashboard_widgets_pkey ON public.dashboard_widgets USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"((tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) AND ((user_id = uid()) OR (user_id IS NULL)))","roles":["public"],"tablename":"dashboard_widgets","permissive":"PERMISSIVE","policyname":"Users can manage own widgets","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"dashboard_widgets_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"data_integrity_quarantine","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"table_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"record_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"snapshot","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"quarantined_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"quarantined_by","type":"text","default":"'system_migration_phase2'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"data_integrity_quarantine_pkey","definition":"CREATE UNIQUE INDEX data_integrity_quarantine_pkey ON public.data_integrity_quarantine USING btree (id)"},{"name":"idx_data_integrity_quarantine_table_record","definition":"CREATE INDEX idx_data_integrity_quarantine_table_record ON public.data_integrity_quarantine USING btree (table_name, record_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"data_integrity_quarantine","permissive":"PERMISSIVE","policyname":"godmode_full_access_quarantine","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"data_integrity_quarantine_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"data_quality_issues","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"table_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"issue_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"severity","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"details","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"auto_fixable","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolution_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"data_quality_issues_pkey","definition":"CREATE UNIQUE INDEX data_quality_issues_pkey ON public.data_quality_issues USING btree (id)"},{"name":"idx_dqi_lead_id","definition":"CREATE INDEX idx_dqi_lead_id ON public.data_quality_issues USING btree (lead_id)"},{"name":"idx_dqi_severity","definition":"CREATE INDEX idx_dqi_severity ON public.data_quality_issues USING btree (severity)"},{"name":"idx_dqi_unresolved","definition":"CREATE INDEX idx_dqi_unresolved ON public.data_quality_issues USING btree (resolved_at) WHERE (resolved_at IS NULL)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM lead_deck ld\n  WHERE ((ld.lead_id = data_quality_issues.lead_id) AND (EXISTS ( SELECT 1\n           FROM user_roles\n          WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = ld.tenant_org_id) AND (user_roles.role = 'Owner'::app_role)))))))","roles":["authenticated"],"tablename":"data_quality_issues","permissive":"PERMISSIVE","policyname":"Tenant owners view tenant quality issues","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"data_quality_issues","permissive":"PERMISSIVE","policyname":"platform_admin_manage_quality_issues","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"data_quality_issues_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"data_retention_policies","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"table_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"retention_days","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"last_executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"data_retention_policies_pkey","definition":"CREATE UNIQUE INDEX data_retention_policies_pkey ON public.data_retention_policies USING btree (id)"},{"name":"data_retention_policies_table_name_key","definition":"CREATE UNIQUE INDEX data_retention_policies_table_name_key ON public.data_retention_policies USING btree (table_name)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"data_retention_policies","permissive":"PERMISSIVE","policyname":"platform_admin_manage_retention","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"data_retention_policies_action_check","definition":"CHECK (action = ANY (ARRAY['delete'::text, 'anonymize'::text, 'archive'::text]))"},{"name":"data_retention_policies_pkey","definition":"PRIMARY KEY (id)"},{"name":"data_retention_policies_table_name_key","definition":"UNIQUE (table_name)"}]},{"table":"dnc_audit_entries","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"run_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_table","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_original","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scan_result","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"was_previously_clean","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"newly_flagged","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"previous_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_match_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_match_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"scanned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"dnc_audit_entries_pkey","definition":"CREATE UNIQUE INDEX dnc_audit_entries_pkey ON public.dnc_audit_entries USING btree (id)"},{"name":"idx_dnc_audit_entries_lead","definition":"CREATE INDEX idx_dnc_audit_entries_lead ON public.dnc_audit_entries USING btree (lead_id, scanned_at DESC)"},{"name":"idx_dnc_audit_entries_newly_flagged","definition":"CREATE INDEX idx_dnc_audit_entries_newly_flagged ON public.dnc_audit_entries USING btree (newly_flagged) WHERE (newly_flagged = true)"},{"name":"idx_dnc_audit_entries_phone","definition":"CREATE INDEX idx_dnc_audit_entries_phone ON public.dnc_audit_entries USING btree (phone_normalized)"},{"name":"idx_dnc_audit_entries_run","definition":"CREATE INDEX idx_dnc_audit_entries_run ON public.dnc_audit_entries USING btree (run_id)"},{"name":"idx_dnc_audit_entries_scanned","definition":"CREATE INDEX idx_dnc_audit_entries_scanned ON public.dnc_audit_entries USING btree (scanned_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"dnc_audit_entries","permissive":"PERMISSIVE","policyname":"Service role manages audit entries","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"dnc_audit_entries","permissive":"PERMISSIVE","policyname":"platform_admin_view_dnc_audit_entries","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_prevent_dnc_audit_update","definition":"CREATE TRIGGER trg_prevent_dnc_audit_update BEFORE DELETE OR UPDATE ON dnc_audit_entries FOR EACH ROW EXECUTE FUNCTION prevent_dnc_audit_modification()"}],"constraints":[{"name":"dnc_audit_entries_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dnc_audit_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"run_type","type":"text","default":"'scheduled'::text","identity":"","not_null":true,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"leads_scanned","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"matches_found","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"newly_flagged","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"errors_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'running'::text","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"triggered_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"dnc_audit_runs_pkey","definition":"CREATE UNIQUE INDEX dnc_audit_runs_pkey ON public.dnc_audit_runs USING btree (id)"},{"name":"idx_dnc_audit_runs_started","definition":"CREATE INDEX idx_dnc_audit_runs_started ON public.dnc_audit_runs USING btree (started_at DESC)"},{"name":"idx_dnc_audit_runs_status","definition":"CREATE INDEX idx_dnc_audit_runs_status ON public.dnc_audit_runs USING btree (status)"}],"policies":[{"cmd":"ALL","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"dnc_audit_runs","permissive":"PERMISSIVE","policyname":"Service role manages audit runs","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"dnc_audit_runs","permissive":"PERMISSIVE","policyname":"platform_admin_view_dnc_audit_runs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"dnc_audit_runs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dnc_federal_numbers","schema":"public","columns":[{"name":"phone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"area_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'ftc_national'::text","identity":"","not_null":true,"generated":""},{"name":"added_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"dnc_federal_numbers_pkey","definition":"CREATE UNIQUE INDEX dnc_federal_numbers_pkey ON public.dnc_federal_numbers USING btree (phone)"},{"name":"idx_dnc_federal_numbers_area_code","definition":"CREATE INDEX idx_dnc_federal_numbers_area_code ON public.dnc_federal_numbers USING btree (area_code)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"dnc_federal_numbers","permissive":"PERMISSIVE","policyname":"Authenticated users lookup federal DNC numbers","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_propagate_fed_dnc","definition":"CREATE TRIGGER trg_propagate_fed_dnc AFTER INSERT ON dnc_federal_numbers FOR EACH ROW EXECUTE FUNCTION propagate_federal_dnc_to_contacts()"}],"constraints":[{"name":"dnc_federal_numbers_pkey","definition":"PRIMARY KEY (phone)"}]},{"table":"dnc_federal_subscriptions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"san","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"organization_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"area_codes","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"login_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_synced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_renewal_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"dnc_federal_subscriptions_pkey","definition":"CREATE UNIQUE INDEX dnc_federal_subscriptions_pkey ON public.dnc_federal_subscriptions USING btree (id)"},{"name":"dnc_federal_subscriptions_tenant_id_key","definition":"CREATE UNIQUE INDEX dnc_federal_subscriptions_tenant_id_key ON public.dnc_federal_subscriptions USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"(has_role(uid(), tenant_id, 'Owner'::app_role) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"dnc_federal_subscriptions","permissive":"PERMISSIVE","policyname":"Owners manage federal DNC subscription","schemaname":"public","with_check":"(has_role(uid(), tenant_id, 'Owner'::app_role) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = dnc_federal_subscriptions.tenant_id)))) OR is_system_admin(uid()))","roles":["public"],"tablename":"dnc_federal_subscriptions","permissive":"PERMISSIVE","policyname":"Tenant members view federal DNC subscription","schemaname":"public","with_check":null}],"triggers":[{"name":"update_dnc_federal_subscriptions_updated_at","definition":"CREATE TRIGGER update_dnc_federal_subscriptions_updated_at BEFORE UPDATE ON dnc_federal_subscriptions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"dnc_federal_subscriptions_pkey","definition":"PRIMARY KEY (id)"},{"name":"dnc_federal_subscriptions_tenant_id_key","definition":"UNIQUE (tenant_id)"}]},{"table":"dnc_florida_registry","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'ftsa_official'::text","identity":"","not_null":true,"generated":""},{"name":"added_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"removed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"dnc_florida_registry_phone_normalized_source_key","definition":"CREATE UNIQUE INDEX dnc_florida_registry_phone_normalized_source_key ON public.dnc_florida_registry USING btree (phone_normalized, source)"},{"name":"dnc_florida_registry_pkey","definition":"CREATE UNIQUE INDEX dnc_florida_registry_pkey ON public.dnc_florida_registry USING btree (id)"},{"name":"idx_dnc_fl_phone","definition":"CREATE INDEX idx_dnc_fl_phone ON public.dnc_florida_registry USING btree (phone_normalized) WHERE (removed_at IS NULL)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"dnc_florida_registry","permissive":"PERMISSIVE","policyname":"authenticated_view_florida_dnc","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin()","roles":["authenticated"],"tablename":"dnc_florida_registry","permissive":"PERMISSIVE","policyname":"system_admins_manage_florida_dnc","schemaname":"public","with_check":"is_system_admin()"}],"triggers":[{"name":"trg_propagate_fl_dnc","definition":"CREATE TRIGGER trg_propagate_fl_dnc AFTER INSERT ON dnc_florida_registry FOR EACH ROW EXECUTE FUNCTION propagate_florida_dnc_to_contacts()"}],"constraints":[{"name":"dnc_florida_registry_phone_normalized_source_key","definition":"UNIQUE (phone_normalized, source)"},{"name":"dnc_florida_registry_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dnc_list","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"added_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"phone_normalized","type":"text","default":"normalize_phone_for_dnc(phone)","identity":"","not_null":false,"generated":"s"},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"batch_id","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"dnc_list_phone_key","definition":"CREATE UNIQUE INDEX dnc_list_phone_key ON public.dnc_list USING btree (phone)"},{"name":"dnc_list_pkey","definition":"CREATE UNIQUE INDEX dnc_list_pkey ON public.dnc_list USING btree (id)"},{"name":"idx_dnc_list_batch_id","definition":"CREATE INDEX idx_dnc_list_batch_id ON public.dnc_list USING btree (batch_id)"},{"name":"idx_dnc_list_phone_normalized","definition":"CREATE INDEX idx_dnc_list_phone_normalized ON public.dnc_list USING btree (phone_normalized)"},{"name":"idx_dnc_list_source","definition":"CREATE INDEX idx_dnc_list_source ON public.dnc_list USING btree (source)"},{"name":"idx_dnc_phone","definition":"CREATE INDEX idx_dnc_phone ON public.dnc_list USING btree (phone)"},{"name":"idx_dnc_phone_normalized","definition":"CREATE INDEX idx_dnc_phone_normalized ON public.dnc_list USING btree (phone_normalized)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"dnc_list","permissive":"PERMISSIVE","policyname":"dnc_godmode_all","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"dnc_list","permissive":"PERMISSIVE","policyname":"dnc_tenant_member_select","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"dnc_list","permissive":"PERMISSIVE","policyname":"dnc_tenant_owner_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"dnc_list","permissive":"PERMISSIVE","policyname":"dnc_tenant_owner_admin_insert","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))"},{"cmd":"UPDATE","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"dnc_list","permissive":"PERMISSIVE","policyname":"dnc_tenant_owner_admin_update","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))"}],"triggers":[{"name":"trg_enforce_dnc_quarantine","definition":"CREATE TRIGGER trg_enforce_dnc_quarantine AFTER INSERT ON dnc_list FOR EACH ROW EXECUTE FUNCTION enforce_dnc_quarantine()"},{"name":"trg_propagate_dnc","definition":"CREATE TRIGGER trg_propagate_dnc AFTER INSERT ON dnc_list FOR EACH ROW EXECUTE FUNCTION propagate_dnc_to_leads()"}],"constraints":[{"name":"dnc_list_phone_key","definition":"UNIQUE (phone)"},{"name":"dnc_list_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dnc_quarantine","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"original_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_table","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_snapshot","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"quarantined_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"quarantined_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"dnc_quarantine_pkey","definition":"CREATE UNIQUE INDEX dnc_quarantine_pkey ON public.dnc_quarantine USING btree (id)"},{"name":"idx_dnc_quarantine_at","definition":"CREATE INDEX idx_dnc_quarantine_at ON public.dnc_quarantine USING btree (quarantined_at DESC)"},{"name":"idx_dnc_quarantine_phone","definition":"CREATE INDEX idx_dnc_quarantine_phone ON public.dnc_quarantine USING btree (phone_normalized)"},{"name":"idx_dnc_quarantine_tenant","definition":"CREATE INDEX idx_dnc_quarantine_tenant ON public.dnc_quarantine USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"dnc_quarantine","permissive":"PERMISSIVE","policyname":"Only system admins may directly insert quarantine","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"dnc_quarantine","permissive":"PERMISSIVE","policyname":"System admins can view quarantine","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_dnc_quarantine_immutable","definition":"CREATE TRIGGER trg_dnc_quarantine_immutable BEFORE DELETE OR UPDATE ON dnc_quarantine FOR EACH ROW EXECUTE FUNCTION prevent_quarantine_modification()"}],"constraints":[{"name":"dnc_quarantine_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dnc_scrub_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"batch_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scope","type":"text","default":"'platform'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"run_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"run_by_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"run_by_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"files","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"total_ftc_numbers","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"contacts_checked","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"matches_quarantined","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"certificate_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"dnc_scrub_runs_pkey","definition":"CREATE UNIQUE INDEX dnc_scrub_runs_pkey ON public.dnc_scrub_runs USING btree (id)"},{"name":"idx_dnc_scrub_runs_created_at","definition":"CREATE INDEX idx_dnc_scrub_runs_created_at ON public.dnc_scrub_runs USING btree (created_at DESC)"},{"name":"idx_dnc_scrub_runs_scope","definition":"CREATE INDEX idx_dnc_scrub_runs_scope ON public.dnc_scrub_runs USING btree (scope)"},{"name":"idx_dnc_scrub_runs_tenant","definition":"CREATE INDEX idx_dnc_scrub_runs_tenant ON public.dnc_scrub_runs USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"dnc_scrub_runs","permissive":"PERMISSIVE","policyname":"platform_admin_manage_dnc_scrub_runs","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = dnc_scrub_runs.tenant_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'Tenant Owner'::app_role, 'Manager'::app_role]))))))","roles":["public"],"tablename":"dnc_scrub_runs","permissive":"PERMISSIVE","policyname":"tenant_owners_view_their_scrub_runs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"dnc_scrub_runs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"dnc_sync_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'running'::text","identity":"","not_null":true,"generated":""},{"name":"area_codes","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"rows_added","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"rows_removed","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"details","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"dnc_sync_log_pkey","definition":"CREATE UNIQUE INDEX dnc_sync_log_pkey ON public.dnc_sync_log USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR ((tenant_id IS NOT NULL) AND has_role(uid(), tenant_id, 'Owner'::app_role)))","roles":["authenticated"],"tablename":"dnc_sync_log","permissive":"PERMISSIVE","policyname":"Admins view sync log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"dnc_sync_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_activity","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"activity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"activity_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_activity_pkey","definition":"CREATE UNIQUE INDEX document_activity_pkey ON public.document_activity USING btree (id)"},{"name":"idx_document_activity_created","definition":"CREATE INDEX idx_document_activity_created ON public.document_activity USING btree (created_at DESC)"},{"name":"idx_document_activity_doc","definition":"CREATE INDEX idx_document_activity_doc ON public.document_activity USING btree (document_id)"},{"name":"idx_document_activity_tenant","definition":"CREATE INDEX idx_document_activity_tenant ON public.document_activity USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"document_activity","permissive":"PERMISSIVE","policyname":"Users can create activity in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"document_activity","permissive":"PERMISSIVE","policyname":"Users can view activity in their tenant","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_activity_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_comments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"comment_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_comments_pkey","definition":"CREATE UNIQUE INDEX document_comments_pkey ON public.document_comments USING btree (id)"},{"name":"idx_document_comments_created","definition":"CREATE INDEX idx_document_comments_created ON public.document_comments USING btree (created_at DESC)"},{"name":"idx_document_comments_doc","definition":"CREATE INDEX idx_document_comments_doc ON public.document_comments USING btree (document_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"document_comments","permissive":"PERMISSIVE","policyname":"Users can create comments in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["public"],"tablename":"document_comments","permissive":"PERMISSIVE","policyname":"Users can update their own comments","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"document_comments","permissive":"PERMISSIVE","policyname":"Users can view comments in their tenant","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_comments_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_drafts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"document_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"content","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_drafts_pkey","definition":"CREATE UNIQUE INDEX document_drafts_pkey ON public.document_drafts USING btree (id)"},{"name":"idx_document_drafts_contact","definition":"CREATE INDEX idx_document_drafts_contact ON public.document_drafts USING btree (contact_id)"},{"name":"idx_document_drafts_created_by","definition":"CREATE INDEX idx_document_drafts_created_by ON public.document_drafts USING btree (created_by)"},{"name":"idx_document_drafts_tenant","definition":"CREATE INDEX idx_document_drafts_tenant ON public.document_drafts USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"document_drafts","permissive":"PERMISSIVE","policyname":"Users can create drafts in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"(created_by = uid())","roles":["public"],"tablename":"document_drafts","permissive":"PERMISSIVE","policyname":"Users can delete their drafts","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(created_by = uid())","roles":["public"],"tablename":"document_drafts","permissive":"PERMISSIVE","policyname":"Users can update their drafts","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"document_drafts","permissive":"PERMISSIVE","policyname":"Users can view drafts in their tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"update_document_drafts_updated_at","definition":"CREATE TRIGGER update_document_drafts_updated_at BEFORE UPDATE ON document_drafts FOR EACH ROW EXECUTE FUNCTION update_document_drafts_updated_at()"}],"constraints":[{"name":"document_drafts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_field_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"pdf_fingerprint","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"field_config","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"field_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"source_file_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_field_templates_pkey","definition":"CREATE UNIQUE INDEX document_field_templates_pkey ON public.document_field_templates USING btree (id)"},{"name":"idx_field_templates_fingerprint","definition":"CREATE INDEX idx_field_templates_fingerprint ON public.document_field_templates USING btree (pdf_fingerprint)"},{"name":"idx_field_templates_tenant","definition":"CREATE INDEX idx_field_templates_tenant ON public.document_field_templates USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"document_field_templates","permissive":"PERMISSIVE","policyname":"Tenant members can create templates","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE (utm.user_id = uid())))"},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE (utm.user_id = uid())))","roles":["authenticated"],"tablename":"document_field_templates","permissive":"PERMISSIVE","policyname":"Tenant members can update templates","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE (utm.user_id = uid())))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = document_field_templates.tenant_org_id)))))","roles":["authenticated"],"tablename":"document_field_templates","permissive":"PERMISSIVE","policyname":"Tenant members can view templates","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_field_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_fill_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"field_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"field_label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"fill_source","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""},{"name":"old_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"confidence","type":"numeric(4,3)","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_fill_audit_pkey","definition":"CREATE UNIQUE INDEX document_fill_audit_pkey ON public.document_fill_audit USING btree (id)"},{"name":"idx_fill_audit_document","definition":"CREATE INDEX idx_fill_audit_document ON public.document_fill_audit USING btree (document_id)"},{"name":"idx_fill_audit_tenant","definition":"CREATE INDEX idx_fill_audit_tenant ON public.document_fill_audit USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"document_fill_audit","permissive":"PERMISSIVE","policyname":"Authenticated users can insert audit entries","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = document_fill_audit.tenant_org_id))))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = document_fill_audit.tenant_org_id)))))","roles":["authenticated"],"tablename":"document_fill_audit","permissive":"PERMISSIVE","policyname":"Tenant members can view fill audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_fill_audit_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"document_fill_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"requested_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"channel","type":"text","default":"'email'::text","identity":"","not_null":true,"generated":""},{"name":"recipient_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recipient_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"share_token","type":"text","default":"encode(gen_random_bytes(24), 'hex'::text)","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":"(now() + '14 days'::interval)","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"uploaded_file_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"uploaded_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reminder_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"last_reminder_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_requests_pkey","definition":"CREATE UNIQUE INDEX document_requests_pkey ON public.document_requests USING btree (id)"},{"name":"document_requests_share_token_key","definition":"CREATE UNIQUE INDEX document_requests_share_token_key ON public.document_requests USING btree (share_token)"},{"name":"idx_document_requests_contact","definition":"CREATE INDEX idx_document_requests_contact ON public.document_requests USING btree (contact_id)"},{"name":"idx_document_requests_tenant","definition":"CREATE INDEX idx_document_requests_tenant ON public.document_requests USING btree (tenant_org_id, status)"},{"name":"idx_document_requests_token","definition":"CREATE INDEX idx_document_requests_token ON public.document_requests USING btree (share_token) WHERE (status = 'pending'::text)"}],"policies":[{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND ((utm.tenant_id)::text = document_requests.tenant_org_id) AND (utm.status = 'active'::text) AND (utm.is_owner = true)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"document_requests","permissive":"PERMISSIVE","policyname":"owner_admin_delete_doc_requests","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"document_requests","permissive":"PERMISSIVE","policyname":"tenant_members_insert_doc_requests","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"document_requests","permissive":"PERMISSIVE","policyname":"tenant_members_select_doc_requests","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"document_requests","permissive":"PERMISSIVE","policyname":"tenant_members_update_doc_requests","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_document_requests_updated_at","definition":"CREATE TRIGGER trg_document_requests_updated_at BEFORE UPDATE ON document_requests FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"document_requests_channel_check","definition":"CHECK (channel = ANY (ARRAY['email'::text, 'sms'::text, 'both'::text, 'link_only'::text]))"},{"name":"document_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"document_requests_share_token_key","definition":"UNIQUE (share_token)"},{"name":"document_requests_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'uploaded'::text, 'expired'::text, 'cancelled'::text]))"}]},{"table":"document_share_links","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"share_token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"password_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"view_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_share_links_pkey","definition":"CREATE UNIQUE INDEX document_share_links_pkey ON public.document_share_links USING btree (id)"},{"name":"document_share_links_share_token_key","definition":"CREATE UNIQUE INDEX document_share_links_share_token_key ON public.document_share_links USING btree (share_token)"},{"name":"idx_document_share_doc","definition":"CREATE INDEX idx_document_share_doc ON public.document_share_links USING btree (document_id)"},{"name":"idx_document_share_token","definition":"CREATE INDEX idx_document_share_token ON public.document_share_links USING btree (share_token)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"document_share_links","permissive":"PERMISSIVE","policyname":"Users can create share links in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"document_share_links","permissive":"PERMISSIVE","policyname":"Users can view share links in their tenant","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_share_links_pkey","definition":"PRIMARY KEY (id)"},{"name":"document_share_links_share_token_key","definition":"UNIQUE (share_token)"}]},{"table":"document_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"document_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"template_data","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"variables","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"usage_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"form_fields","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"field_mappings","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"pdf_template_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_fillable_pdf","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"document_templates_pkey","definition":"CREATE UNIQUE INDEX document_templates_pkey ON public.document_templates USING btree (id)"},{"name":"idx_document_templates_tenant","definition":"CREATE INDEX idx_document_templates_tenant ON public.document_templates USING btree (tenant_org_id)"},{"name":"idx_document_templates_type","definition":"CREATE INDEX idx_document_templates_type ON public.document_templates USING btree (document_type, tenant_type)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"document_templates","permissive":"PERMISSIVE","policyname":"Users can create templates in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"((tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"document_templates","permissive":"PERMISSIVE","policyname":"Users can delete templates in their tenant","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"document_templates","permissive":"PERMISSIVE","policyname":"Users can update templates in their tenant","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"document_templates","permissive":"PERMISSIVE","policyname":"Users can view templates in their tenant","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"document_versions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_file_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"version_number","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_size","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"mime_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changes_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"document_versions_contact_file_id_version_number_key","definition":"CREATE UNIQUE INDEX document_versions_contact_file_id_version_number_key ON public.document_versions USING btree (contact_file_id, version_number)"},{"name":"document_versions_pkey","definition":"CREATE UNIQUE INDEX document_versions_pkey ON public.document_versions USING btree (id)"},{"name":"idx_document_versions_contact_file_id","definition":"CREATE INDEX idx_document_versions_contact_file_id ON public.document_versions USING btree (contact_file_id)"},{"name":"idx_document_versions_created_at","definition":"CREATE INDEX idx_document_versions_created_at ON public.document_versions USING btree (created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"document_versions","permissive":"PERMISSIVE","policyname":"Users create document versions","schemaname":"public","with_check":"(uid() = created_by)"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM (contact_files cf\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = cf.tenant_org_id)))\n  WHERE ((cf.id = document_versions.contact_file_id) AND (utm.user_id = uid()))))","roles":["public"],"tablename":"document_versions","permissive":"PERMISSIVE","policyname":"Users view document versions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"document_versions_contact_file_id_version_number_key","definition":"UNIQUE (contact_file_id, version_number)"},{"name":"document_versions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"documents","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"scope","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"mime_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_file_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"drive_web_view_link","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"uploaded_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"uploaded_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"documents_event_booking_idx","definition":"CREATE INDEX documents_event_booking_idx ON public.documents USING btree (event_booking_id)"},{"name":"documents_pkey","definition":"CREATE UNIQUE INDEX documents_pkey ON public.documents USING btree (id)"},{"name":"idx_documents_category","definition":"CREATE INDEX idx_documents_category ON public.documents USING btree (category)"},{"name":"idx_documents_scope","definition":"CREATE INDEX idx_documents_scope ON public.documents USING btree (scope)"},{"name":"idx_documents_tenant","definition":"CREATE INDEX idx_documents_tenant ON public.documents USING btree (tenant_id)"},{"name":"idx_documents_uploaded_at","definition":"CREATE INDEX idx_documents_uploaded_at ON public.documents USING btree (uploaded_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"((tenant_id IS NULL) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = documents.tenant_id)))))","roles":["authenticated"],"tablename":"documents","permissive":"PERMISSIVE","policyname":"Users can view accessible documents","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"documents","permissive":"PERMISSIVE","policyname":"platform_admin_manage_documents","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"documents","permissive":"PERMISSIVE","policyname":"tenant_members_manage_documents","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND is_tenant_member(uid(), tenant_id))"}],"triggers":[],"constraints":[{"name":"documents_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"documents_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"door_notes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"visit_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"author_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"author_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"author_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"visibility","type":"text","default":"'internal'::text","identity":"","not_null":true,"generated":""},{"name":"note_type","type":"text","default":"'general'::text","identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"edited_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"door_notes_pkey","definition":"CREATE UNIQUE INDEX door_notes_pkey ON public.door_notes USING btree (id)"},{"name":"idx_door_notes_author","definition":"CREATE INDEX idx_door_notes_author ON public.door_notes USING btree (author_id)"},{"name":"idx_door_notes_door","definition":"CREATE INDEX idx_door_notes_door ON public.door_notes USING btree (door_id, created_at DESC)"},{"name":"idx_door_notes_tenant","definition":"CREATE INDEX idx_door_notes_tenant ON public.door_notes USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"UPDATE","qual":"((author_id = uid()) AND (created_at > (now() - '00:15:00'::interval)))","roles":["authenticated"],"tablename":"door_notes","permissive":"PERMISSIVE","policyname":"door_notes_author_edit_window","schemaname":"public","with_check":"(author_id = uid())"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"door_notes","permissive":"PERMISSIVE","policyname":"door_notes_tenant_insert","schemaname":"public","with_check":"((author_id = uid()) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = door_notes.tenant_org_id) AND (utm.status = 'active'::text)))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = door_notes.tenant_org_id) AND (utm.status = 'active'::text))))","roles":["authenticated"],"tablename":"door_notes","permissive":"PERMISSIVE","policyname":"door_notes_tenant_read","schemaname":"public","with_check":null}],"triggers":[{"name":"door_notes_stamp_edited","definition":"CREATE TRIGGER door_notes_stamp_edited BEFORE UPDATE ON door_notes FOR EACH ROW EXECUTE FUNCTION tg_door_notes_stamp_edited()"}],"constraints":[{"name":"door_notes_body_not_empty","definition":"CHECK (length(TRIM(BOTH FROM body)) > 0)"},{"name":"door_notes_note_type_check","definition":"CHECK (note_type = ANY (ARRAY['general'::text, 'visit'::text, 'status_change'::text, 'contact'::text, 'followup'::text, 'system'::text]))"},{"name":"door_notes_pkey","definition":"PRIMARY KEY (id)"},{"name":"door_notes_visibility_check","definition":"CHECK (visibility = ANY (ARRAY['internal'::text, 'public'::text, 'system'::text]))"}]},{"table":"door_objects","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"territory_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":true,"generated":""},{"name":"current_status","type":"door_result_status","default":"'not_home'::door_result_status","identity":"","not_null":false,"generated":""},{"name":"last_result_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_visited_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"deletion_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'crm'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"door_objects_pkey","definition":"CREATE UNIQUE INDEX door_objects_pkey ON public.door_objects USING btree (id)"},{"name":"idx_door_objects_contact_id","definition":"CREATE INDEX idx_door_objects_contact_id ON public.door_objects USING btree (contact_id) WHERE (contact_id IS NOT NULL)"},{"name":"idx_door_objects_deleted_at","definition":"CREATE INDEX idx_door_objects_deleted_at ON public.door_objects USING btree (deleted_at) WHERE (deleted_at IS NULL)"},{"name":"idx_door_objects_location","definition":"CREATE INDEX idx_door_objects_location ON public.door_objects USING btree (lat, lng)"},{"name":"idx_door_objects_status","definition":"CREATE INDEX idx_door_objects_status ON public.door_objects USING btree (current_status)"},{"name":"idx_door_objects_tenant","definition":"CREATE INDEX idx_door_objects_tenant ON public.door_objects USING btree (tenant_org_id)"},{"name":"idx_door_objects_territory","definition":"CREATE INDEX idx_door_objects_territory ON public.door_objects USING btree (territory_id)"}],"policies":[{"cmd":"ALL","qual":"((deleted_at IS NULL) AND (tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))))","roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Tenant members manage active doors","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can create doors","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can create doors in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can delete doors in their tenant","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((uid() = created_by) OR (EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (door_objects.tenant_org_id)::uuid) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can delete doors they created","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can insert doors in their tenant","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (door_objects.tenant_org_id)::uuid))))"},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can update doors","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can update doors in their tenant","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"UPDATE","qual":"is_door_accessible(tenant_org_id, created_by, last_visited_by)","roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users can update doors they can access","schemaname":"public","with_check":"is_door_accessible(tenant_org_id, created_by, last_visited_by)"},{"cmd":"ALL","qual":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) AND ((territory_id IS NULL) OR (territory_id IN ( SELECT territory_assignments.territory_id\n   FROM territory_assignments\n  WHERE (territory_assignments.user_id = uid())))))","roles":["public"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users manage doors in assigned territories","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((deleted_at IS NULL) AND (tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))))","roles":["authenticated"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"Users view active tenant doors","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"do_all","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"door_objects_godmode_view_all","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"door_objects","permissive":"PERMISSIVE","policyname":"door_objects_tenant_owner_view_all","schemaname":"public","with_check":null}],"triggers":[{"name":"set_door_created_by_trigger","definition":"CREATE TRIGGER set_door_created_by_trigger BEFORE INSERT ON door_objects FOR EACH ROW EXECUTE FUNCTION set_door_created_by()"}],"constraints":[{"name":"door_objects_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"door_scores","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"best_visit_hour","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"best_day_of_week","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scoring_factors","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"calculated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":"(now() + '24:00:00'::interval)","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"door_scores_door_id_key","definition":"CREATE UNIQUE INDEX door_scores_door_id_key ON public.door_scores USING btree (door_id)"},{"name":"door_scores_pkey","definition":"CREATE UNIQUE INDEX door_scores_pkey ON public.door_scores USING btree (id)"},{"name":"idx_door_scores_door_id","definition":"CREATE INDEX idx_door_scores_door_id ON public.door_scores USING btree (door_id)"},{"name":"idx_door_scores_score","definition":"CREATE INDEX idx_door_scores_score ON public.door_scores USING btree (score DESC)"},{"name":"idx_door_scores_tenant","definition":"CREATE INDEX idx_door_scores_tenant ON public.door_scores USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = door_scores.tenant_org_id))))","roles":["public"],"tablename":"door_scores","permissive":"PERMISSIVE","policyname":"Tenant members view door scores","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"door_scores_best_visit_hour_check","definition":"CHECK (best_visit_hour >= 0 AND best_visit_hour <= 23)"},{"name":"door_scores_door_id_key","definition":"UNIQUE (door_id)"},{"name":"door_scores_pkey","definition":"PRIMARY KEY (id)"},{"name":"door_scores_score_check","definition":"CHECK (score >= 0 AND score <= 100)"}]},{"table":"door_status_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"visit_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"previous_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'visit'::text","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"door_status_history_pkey","definition":"CREATE UNIQUE INDEX door_status_history_pkey ON public.door_status_history USING btree (id)"},{"name":"idx_door_status_history_door","definition":"CREATE INDEX idx_door_status_history_door ON public.door_status_history USING btree (door_id, created_at DESC)"},{"name":"idx_door_status_history_tenant","definition":"CREATE INDEX idx_door_status_history_tenant ON public.door_status_history USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"door_status_history","permissive":"PERMISSIVE","policyname":"door_status_history_tenant_insert","schemaname":"public","with_check":"((actor_id = uid()) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = door_status_history.tenant_org_id) AND (utm.status = 'active'::text)))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = door_status_history.tenant_org_id) AND (utm.status = 'active'::text))))","roles":["authenticated"],"tablename":"door_status_history","permissive":"PERMISSIVE","policyname":"door_status_history_tenant_read","schemaname":"public","with_check":null}],"triggers":[{"name":"door_status_to_timeline","definition":"CREATE TRIGGER door_status_to_timeline AFTER INSERT ON door_status_history FOR EACH ROW EXECUTE FUNCTION tg_door_status_to_timeline()"}],"constraints":[{"name":"door_status_history_pkey","definition":"PRIMARY KEY (id)"},{"name":"door_status_history_source_check","definition":"CHECK (source = ANY (ARRAY['visit'::text, 'manual'::text, 'system'::text, 'batch'::text, 'import'::text]))"}]},{"table":"door_visit_media","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"visit_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"media_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"caption","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"transcription","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"file_size_bytes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"compressed","type":"boolean","default":"false","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"door_visit_media_pkey","definition":"CREATE UNIQUE INDEX door_visit_media_pkey ON public.door_visit_media USING btree (id)"},{"name":"idx_door_visit_media_visit","definition":"CREATE INDEX idx_door_visit_media_visit ON public.door_visit_media USING btree (visit_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"door_visit_media","permissive":"PERMISSIVE","policyname":"Users can create visit media","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM door_visits\n  WHERE ((door_visits.id = door_visit_media.visit_id) AND (door_visits.user_id = uid())))) OR (EXISTS ( SELECT 1\n   FROM (door_visits dv\n     JOIN user_roles ur ON (((ur.user_id = uid()) AND (ur.tenant_id = (dv.tenant_org_id)::uuid) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))\n  WHERE (dv.id = door_visit_media.visit_id))))","roles":["authenticated"],"tablename":"door_visit_media","permissive":"PERMISSIVE","policyname":"Users can delete their visit media","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"door_visit_media","permissive":"PERMISSIVE","policyname":"Users can insert visit media","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM door_visits\n  WHERE ((door_visits.id = door_visit_media.visit_id) AND (door_visits.user_id = uid()))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM door_visits dv\n  WHERE ((dv.id = door_visit_media.visit_id) AND (dv.user_id = uid())))) OR (EXISTS ( SELECT 1\n   FROM ((door_visits dv\n     JOIN user_roles ur ON (((ur.user_id = uid()) AND (ur.tenant_id = (dv.tenant_org_id)::uuid))))\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = ur.user_id) AND (m.tenant_id = ur.tenant_id))))\n  WHERE ((dv.id = door_visit_media.visit_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"door_visit_media","permissive":"PERMISSIVE","policyname":"Users can view visit media","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"door_visit_media","permissive":"PERMISSIVE","policyname":"Users can view visit media in their tenant","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"door_visit_media_media_type_check","definition":"CHECK (media_type = ANY (ARRAY['photo'::text, 'video'::text, 'document'::text]))"},{"name":"door_visit_media_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"door_visits","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"visited_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"result_status","type":"door_result_status","default":null,"identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"follow_up_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"synced","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"offline_created_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"route_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"visit_sequence","type":"integer","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"door_visits_pkey","definition":"CREATE UNIQUE INDEX door_visits_pkey ON public.door_visits USING btree (id)"},{"name":"idx_door_visits_created_contact_id","definition":"CREATE INDEX idx_door_visits_created_contact_id ON public.door_visits USING btree (created_contact_id) WHERE (created_contact_id IS NOT NULL)"},{"name":"idx_door_visits_door","definition":"CREATE INDEX idx_door_visits_door ON public.door_visits USING btree (door_id)"},{"name":"idx_door_visits_route","definition":"CREATE INDEX idx_door_visits_route ON public.door_visits USING btree (route_id, visit_sequence)"},{"name":"idx_door_visits_synced","definition":"CREATE INDEX idx_door_visits_synced ON public.door_visits USING btree (synced, offline_created_at)"},{"name":"idx_door_visits_tenant","definition":"CREATE INDEX idx_door_visits_tenant ON public.door_visits USING btree (tenant_org_id)"},{"name":"idx_door_visits_user","definition":"CREATE INDEX idx_door_visits_user ON public.door_visits USING btree (user_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"Users can create visits","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) AND (user_id = uid()))"},{"cmd":"DELETE","qual":"((user_id = uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (door_visits.tenant_org_id)::uuid) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"Users can delete their own visits","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"Users can insert their own visits","schemaname":"public","with_check":"((user_id = uid()) AND (EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (door_visits.tenant_org_id)::uuid)))))"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"Users can update their own visits","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = ur.user_id) AND (m.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = (door_visits.tenant_org_id)::uuid) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"Users can view accessible visits","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"Users can view visits in their tenant","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"door_visits","permissive":"PERMISSIVE","policyname":"dv_all","schemaname":"public","with_check":null}],"triggers":[{"name":"auto_create_recontact_trigger","definition":"CREATE TRIGGER auto_create_recontact_trigger AFTER INSERT ON door_visits FOR EACH ROW EXECUTE FUNCTION auto_create_recontact()"},{"name":"trigger_update_door_status","definition":"CREATE TRIGGER trigger_update_door_status AFTER INSERT ON door_visits FOR EACH ROW EXECUTE FUNCTION update_door_object_status()"},{"name":"update_canvassing_stats_trigger","definition":"CREATE TRIGGER update_canvassing_stats_trigger AFTER INSERT ON door_visits FOR EACH ROW EXECUTE FUNCTION update_canvassing_stats()"}],"constraints":[{"name":"door_visits_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"duplicate_detection_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_id_1","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_id_2","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"similarity_score","type":"numeric(5,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"match_fields","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"duplicate_detection_log_pkey","definition":"CREATE UNIQUE INDEX duplicate_detection_log_pkey ON public.duplicate_detection_log USING btree (id)"},{"name":"idx_duplicate_detection_status","definition":"CREATE INDEX idx_duplicate_detection_status ON public.duplicate_detection_log USING btree (status)"},{"name":"idx_duplicate_detection_tenant","definition":"CREATE INDEX idx_duplicate_detection_tenant ON public.duplicate_detection_log USING btree (tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = duplicate_detection_log.tenant_id))))","roles":["public"],"tablename":"duplicate_detection_log","permissive":"PERMISSIVE","policyname":"Users view tenant duplicates","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"duplicate_detection_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"duplicate_detection_results","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id_1","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id_2","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"confidence_score","type":"numeric(5,4)","default":null,"identity":"","not_null":true,"generated":""},{"name":"matching_fields","type":"text[]","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"merged_to_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"auto_detected","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"duplicate_detection_results_lead_id_1_lead_id_2_key","definition":"CREATE UNIQUE INDEX duplicate_detection_results_lead_id_1_lead_id_2_key ON public.duplicate_detection_results USING btree (lead_id_1, lead_id_2)"},{"name":"duplicate_detection_results_pkey","definition":"CREATE UNIQUE INDEX duplicate_detection_results_pkey ON public.duplicate_detection_results USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"duplicate_detection_results","permissive":"PERMISSIVE","policyname":"Tenant isolation for duplicate_detection_results","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"duplicate_detection_results_lead_id_1_lead_id_2_key","definition":"UNIQUE (lead_id_1, lead_id_2)"},{"name":"duplicate_detection_results_pkey","definition":"PRIMARY KEY (id)"},{"name":"duplicate_detection_results_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'merged'::text, 'dismissed'::text, 'reviewed'::text]))"}]},{"table":"duplicate_merge_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"merge_date","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"merged_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"keeper_record_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"merged_record_ids","type":"uuid[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"merge_strategy","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"merged_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"merge_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"can_undo","type":"boolean","default":"true","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"duplicate_merge_audit_pkey","definition":"CREATE UNIQUE INDEX duplicate_merge_audit_pkey ON public.duplicate_merge_audit USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"duplicate_merge_audit","permissive":"PERMISSIVE","policyname":"System admins can manage merge audit","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"duplicate_merge_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"elevated_patch_audit_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"request_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"elevated_patch_audit_events_pkey","definition":"CREATE UNIQUE INDEX elevated_patch_audit_events_pkey ON public.elevated_patch_audit_events USING btree (id)"},{"name":"idx_epae_request_created","definition":"CREATE INDEX idx_epae_request_created ON public.elevated_patch_audit_events USING btree (request_id, created_at)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin() OR (actor_user_id = uid()) OR (EXISTS ( SELECT 1\n   FROM elevated_patch_requests r\n  WHERE ((r.request_id = elevated_patch_audit_events.request_id) AND (r.tenant_id IS NOT NULL) AND is_tenant_member(uid(), r.tenant_id)))))","roles":["authenticated"],"tablename":"elevated_patch_audit_events","permissive":"PERMISSIVE","policyname":"epae_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"elevated_patch_audit_events_event_type_check","definition":"CHECK (event_type = ANY (ARRAY['planned'::text, 'approved'::text, 'running'::text, 'succeeded'::text, 'failed'::text, 'cancelled'::text, 'rolled_back'::text]))"},{"name":"elevated_patch_audit_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"elevated_patch_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"request_id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"command_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"parsed_intent","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"verb","type":"text","default":"'unsupported'::text","identity":"","not_null":true,"generated":""},{"name":"target_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"generated_plan","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"plan_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"approved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_plan_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'awaiting_approval'::text","identity":"","not_null":true,"generated":""},{"name":"action_taken","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"result","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"supported","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"authorized","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"risk_level","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pre_approved_by_godmode","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"human_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"elevated_patch_requests_pkey","definition":"CREATE UNIQUE INDEX elevated_patch_requests_pkey ON public.elevated_patch_requests USING btree (id)"},{"name":"elevated_patch_requests_request_id_key","definition":"CREATE UNIQUE INDEX elevated_patch_requests_request_id_key ON public.elevated_patch_requests USING btree (request_id)"},{"name":"idx_elevated_patch_requests_actor_created","definition":"CREATE INDEX idx_elevated_patch_requests_actor_created ON public.elevated_patch_requests USING btree (actor_user_id, created_at DESC)"},{"name":"idx_epr_actor_created","definition":"CREATE INDEX idx_epr_actor_created ON public.elevated_patch_requests USING btree (actor_user_id, created_at DESC)"},{"name":"idx_epr_status","definition":"CREATE INDEX idx_epr_status ON public.elevated_patch_requests USING btree (status)"},{"name":"idx_epr_tenant_created","definition":"CREATE INDEX idx_epr_tenant_created ON public.elevated_patch_requests USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin() OR (actor_user_id = uid()) OR ((tenant_id IS NOT NULL) AND is_tenant_member(uid(), tenant_id)))","roles":["authenticated"],"tablename":"elevated_patch_requests","permissive":"PERMISSIVE","policyname":"epr_select","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_touch_elevated_patch_requests","definition":"CREATE TRIGGER trg_touch_elevated_patch_requests BEFORE UPDATE ON elevated_patch_requests FOR EACH ROW EXECUTE FUNCTION touch_elevated_patch_requests()"}],"constraints":[{"name":"elevated_patch_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"elevated_patch_requests_request_id_key","definition":"UNIQUE (request_id)"},{"name":"elevated_patch_requests_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'awaiting_approval'::text, 'approved'::text, 'running'::text, 'succeeded'::text, 'failed'::text, 'cancelled'::text, 'rolled_back'::text]))"}]},{"table":"email_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":false,"generated":""},{"name":"scheduled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"recipient_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"opened_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"clicked_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"email_campaigns_pkey","definition":"CREATE UNIQUE INDEX email_campaigns_pkey ON public.email_campaigns USING btree (id)"},{"name":"idx_email_campaigns_status","definition":"CREATE INDEX idx_email_campaigns_status ON public.email_campaigns USING btree (status)"},{"name":"idx_email_campaigns_tenant_id","definition":"CREATE INDEX idx_email_campaigns_tenant_id ON public.email_campaigns USING btree (tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = email_campaigns.tenant_id))))","roles":["public"],"tablename":"email_campaigns","permissive":"PERMISSIVE","policyname":"Users view tenant campaigns","schemaname":"public","with_check":null}],"triggers":[{"name":"email_campaigns_updated_at","definition":"CREATE TRIGGER email_campaigns_updated_at BEFORE UPDATE ON email_campaigns FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"email_campaigns_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"email_messages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"recipient_email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"sender_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"sender_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sender_display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"provider_message_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"idempotency_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"email_messages_event_booking_idx","definition":"CREATE INDEX email_messages_event_booking_idx ON public.email_messages USING btree (event_booking_id)"},{"name":"email_messages_pkey","definition":"CREATE UNIQUE INDEX email_messages_pkey ON public.email_messages USING btree (id)"},{"name":"email_messages_tenant_idem_uidx","definition":"CREATE UNIQUE INDEX email_messages_tenant_idem_uidx ON public.email_messages USING btree (tenant_org_id, idempotency_key) WHERE (idempotency_key IS NOT NULL)"},{"name":"idx_email_messages_contact","definition":"CREATE INDEX idx_email_messages_contact ON public.email_messages USING btree (contact_id)"},{"name":"idx_email_messages_sender","definition":"CREATE INDEX idx_email_messages_sender ON public.email_messages USING btree (sender_user_id)"},{"name":"idx_email_messages_status","definition":"CREATE INDEX idx_email_messages_status ON public.email_messages USING btree (status)"},{"name":"idx_email_messages_tenant","definition":"CREATE INDEX idx_email_messages_tenant ON public.email_messages USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(NOT is_tenant_crew_only(uid(), tenant_org_id))","roles":["authenticated"],"tablename":"email_messages","permissive":"RESTRICTIVE","policyname":"email_messages_block_crew","schemaname":"public","with_check":"(NOT is_tenant_crew_only(uid(), tenant_org_id))"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"email_messages","permissive":"PERMISSIVE","policyname":"email_messages_godmode_read","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((sender_user_id = uid()) AND is_tenant_member(uid(), tenant_org_id))","roles":["public"],"tablename":"email_messages","permissive":"PERMISSIVE","policyname":"email_messages_self_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"email_messages","permissive":"PERMISSIVE","policyname":"email_messages_service_role","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"SELECT","qual":"(is_tenant_owner_or_admin(uid(), tenant_org_id) OR is_manager_or_higher(uid(), tenant_org_id))","roles":["public"],"tablename":"email_messages","permissive":"PERMISSIVE","policyname":"email_messages_tenant_managers_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"email_messages_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"email_messages_pkey","definition":"PRIMARY KEY (id)"},{"name":"email_messages_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'queued'::text, 'sent'::text, 'failed'::text, 'bounced'::text]))"}]},{"table":"email_send_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"message_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"recipient_email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"email_send_log_pkey","definition":"CREATE UNIQUE INDEX email_send_log_pkey ON public.email_send_log USING btree (id)"},{"name":"idx_email_send_log_created","definition":"CREATE INDEX idx_email_send_log_created ON public.email_send_log USING btree (created_at DESC)"},{"name":"idx_email_send_log_message","definition":"CREATE INDEX idx_email_send_log_message ON public.email_send_log USING btree (message_id)"},{"name":"idx_email_send_log_message_sent_unique","definition":"CREATE UNIQUE INDEX idx_email_send_log_message_sent_unique ON public.email_send_log USING btree (message_id) WHERE (status = 'sent'::text)"},{"name":"idx_email_send_log_recipient","definition":"CREATE INDEX idx_email_send_log_recipient ON public.email_send_log USING btree (recipient_email)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"email_send_log","permissive":"PERMISSIVE","policyname":"Service role can insert send log","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"SELECT","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"email_send_log","permissive":"PERMISSIVE","policyname":"Service role can read send log","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"email_send_log","permissive":"PERMISSIVE","policyname":"Service role can update send log","schemaname":"public","with_check":"(role() = 'service_role'::text)"}],"triggers":[],"constraints":[{"name":"email_send_log_pkey","definition":"PRIMARY KEY (id)"},{"name":"email_send_log_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'sent'::text, 'suppressed'::text, 'failed'::text, 'bounced'::text, 'complained'::text, 'dlq'::text]))"}]},{"table":"email_send_state","schema":"public","columns":[{"name":"id","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"retry_after_until","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"batch_size","type":"integer","default":"10","identity":"","not_null":true,"generated":""},{"name":"send_delay_ms","type":"integer","default":"200","identity":"","not_null":true,"generated":""},{"name":"auth_email_ttl_minutes","type":"integer","default":"15","identity":"","not_null":true,"generated":""},{"name":"transactional_email_ttl_minutes","type":"integer","default":"60","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"email_send_state_pkey","definition":"CREATE UNIQUE INDEX email_send_state_pkey ON public.email_send_state USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"email_send_state","permissive":"PERMISSIVE","policyname":"Service role can manage send state","schemaname":"public","with_check":"(role() = 'service_role'::text)"}],"triggers":[],"constraints":[{"name":"email_send_state_id_check","definition":"CHECK (id = 1)"},{"name":"email_send_state_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"email_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"variables","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"template_context","type":"text","default":"'all'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"email_templates_pkey","definition":"CREATE UNIQUE INDEX email_templates_pkey ON public.email_templates USING btree (id)"},{"name":"idx_email_templates_category","definition":"CREATE INDEX idx_email_templates_category ON public.email_templates USING btree (category)"},{"name":"idx_email_templates_context","definition":"CREATE INDEX idx_email_templates_context ON public.email_templates USING btree (tenant_id, template_context, is_active)"},{"name":"idx_email_templates_tenant_id","definition":"CREATE INDEX idx_email_templates_tenant_id ON public.email_templates USING btree (tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = email_templates.tenant_id))))","roles":["public"],"tablename":"email_templates","permissive":"PERMISSIVE","policyname":"Users view tenant templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_id IS NULL) OR (NOT is_tenant_crew_only(uid(), (tenant_id)::uuid)))","roles":["authenticated"],"tablename":"email_templates","permissive":"RESTRICTIVE","policyname":"email_templates_block_crew","schemaname":"public","with_check":"((tenant_id IS NULL) OR (NOT is_tenant_crew_only(uid(), (tenant_id)::uuid)))"},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"email_templates","permissive":"PERMISSIVE","policyname":"email_templates_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND is_manager_or_higher(uid(), (tenant_id)::uuid))","roles":["public"],"tablename":"email_templates","permissive":"PERMISSIVE","policyname":"email_templates_manager_manage","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND is_manager_or_higher(uid(), (tenant_id)::uuid))"},{"cmd":"SELECT","qual":"((tenant_id IS NULL) OR is_tenant_member(uid(), (tenant_id)::uuid))","roles":["public"],"tablename":"email_templates","permissive":"PERMISSIVE","policyname":"email_templates_tenant_member_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_id)::uuid))","roles":["public"],"tablename":"email_templates","permissive":"PERMISSIVE","policyname":"email_templates_tenant_owner_manage","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_id)::uuid))"}],"triggers":[{"name":"email_templates_updated_at","definition":"CREATE TRIGGER email_templates_updated_at BEFORE UPDATE ON email_templates FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"email_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"email_templates_template_context_check","definition":"CHECK (template_context = ANY (ARRAY['contact'::text, 'appointment'::text, 'all'::text, 'event_booking'::text]))"}]},{"table":"email_tracking_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"email_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"link_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"email_tracking_events_pkey","definition":"CREATE UNIQUE INDEX email_tracking_events_pkey ON public.email_tracking_events USING btree (id)"},{"name":"idx_email_tracking_contact","definition":"CREATE INDEX idx_email_tracking_contact ON public.email_tracking_events USING btree (contact_id)"},{"name":"idx_email_tracking_email","definition":"CREATE INDEX idx_email_tracking_email ON public.email_tracking_events USING btree (email_id)"},{"name":"idx_email_tracking_tenant","definition":"CREATE INDEX idx_email_tracking_tenant ON public.email_tracking_events USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"email_tracking_events","permissive":"PERMISSIVE","policyname":"Tenant isolation for email_tracking_events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"email_tracking_events_event_type_check","definition":"CHECK (event_type = ANY (ARRAY['sent'::text, 'delivered'::text, 'opened'::text, 'clicked'::text, 'bounced'::text, 'complained'::text, 'unsubscribed'::text]))"},{"name":"email_tracking_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"email_unsubscribe_tokens","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"used_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"email_unsubscribe_tokens_email_key","definition":"CREATE UNIQUE INDEX email_unsubscribe_tokens_email_key ON public.email_unsubscribe_tokens USING btree (email)"},{"name":"email_unsubscribe_tokens_pkey","definition":"CREATE UNIQUE INDEX email_unsubscribe_tokens_pkey ON public.email_unsubscribe_tokens USING btree (id)"},{"name":"email_unsubscribe_tokens_token_key","definition":"CREATE UNIQUE INDEX email_unsubscribe_tokens_token_key ON public.email_unsubscribe_tokens USING btree (token)"},{"name":"idx_unsubscribe_tokens_token","definition":"CREATE INDEX idx_unsubscribe_tokens_token ON public.email_unsubscribe_tokens USING btree (token)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"email_unsubscribe_tokens","permissive":"PERMISSIVE","policyname":"Service role can insert tokens","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"UPDATE","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"email_unsubscribe_tokens","permissive":"PERMISSIVE","policyname":"Service role can mark tokens as used","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"SELECT","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"email_unsubscribe_tokens","permissive":"PERMISSIVE","policyname":"Service role can read tokens","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"email_unsubscribe_tokens_email_key","definition":"UNIQUE (email)"},{"name":"email_unsubscribe_tokens_pkey","definition":"PRIMARY KEY (id)"},{"name":"email_unsubscribe_tokens_token_key","definition":"UNIQUE (token)"}]},{"table":"email_unsubscribes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"unsubscribed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"resubscribed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"email_unsubscribes_pkey","definition":"CREATE UNIQUE INDEX email_unsubscribes_pkey ON public.email_unsubscribes USING btree (id)"},{"name":"email_unsubscribes_tenant_id_email_key","definition":"CREATE UNIQUE INDEX email_unsubscribes_tenant_id_email_key ON public.email_unsubscribes USING btree (tenant_id, email)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"email_unsubscribes","permissive":"PERMISSIVE","policyname":"Tenant isolation for email_unsubscribes","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"email_unsubscribes_pkey","definition":"PRIMARY KEY (id)"},{"name":"email_unsubscribes_tenant_id_email_key","definition":"UNIQUE (tenant_id, email)"}]},{"table":"enrichment_queue","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"total_contacts","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"processed","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"enriched","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"failed","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_invocation_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"invocation_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"current_offset","type":"integer","default":"0","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"enrichment_queue_pkey","definition":"CREATE UNIQUE INDEX enrichment_queue_pkey ON public.enrichment_queue USING btree (id)"},{"name":"idx_enrichment_queue_tenant_status","definition":"CREATE INDEX idx_enrichment_queue_tenant_status ON public.enrichment_queue USING btree (tenant_org_id, status)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"enrichment_queue","permissive":"PERMISSIVE","policyname":"Users can create enrichment jobs for their tenant","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))","roles":["public"],"tablename":"enrichment_queue","permissive":"PERMISSIVE","policyname":"Users can view their tenant enrichment jobs","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"enrichment_queue","permissive":"PERMISSIVE","policyname":"tenant_members_update_enrichment","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"enrichment_queue_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"estimate_share_links","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"share_token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"password_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"view_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"allow_acceptance","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"accepted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"accepted_signature","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"accepted_ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"estimate_share_links_pkey","definition":"CREATE UNIQUE INDEX estimate_share_links_pkey ON public.estimate_share_links USING btree (id)"},{"name":"estimate_share_links_share_token_key","definition":"CREATE UNIQUE INDEX estimate_share_links_share_token_key ON public.estimate_share_links USING btree (share_token)"},{"name":"idx_share_links_estimate","definition":"CREATE INDEX idx_share_links_estimate ON public.estimate_share_links USING btree (estimate_id)"},{"name":"idx_share_links_token","definition":"CREATE INDEX idx_share_links_token ON public.estimate_share_links USING btree (share_token)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"estimate_share_links","permissive":"PERMISSIVE","policyname":"Users create tenant share links","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"estimate_share_links","permissive":"PERMISSIVE","policyname":"Users delete tenant share links","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"estimate_share_links","permissive":"PERMISSIVE","policyname":"Users update tenant share links","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"estimate_share_links","permissive":"PERMISSIVE","policyname":"Users view tenant share links","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(share_token = ((current_setting('request.headers'::text, true))::json ->> 'x-share-token'::text))","roles":["anon","authenticated"],"tablename":"estimate_share_links","permissive":"PERMISSIVE","policyname":"View by share token only","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"estimate_share_links_pkey","definition":"PRIMARY KEY (id)"},{"name":"estimate_share_links_share_token_key","definition":"UNIQUE (share_token)"}]},{"table":"estimate_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"manufacturer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"shingle_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"underlayment_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"material_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"labor_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"default_margin_pct","type":"numeric","default":"20","identity":"","not_null":false,"generated":""},{"name":"default_tax_pct","type":"numeric","default":"7","identity":"","not_null":false,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"estimate_templates_pkey","definition":"CREATE UNIQUE INDEX estimate_templates_pkey ON public.estimate_templates USING btree (id)"},{"name":"idx_templates_tenant","definition":"CREATE INDEX idx_templates_tenant ON public.estimate_templates USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"estimate_templates","permissive":"PERMISSIVE","policyname":"Users create tenant templates","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"estimate_templates","permissive":"PERMISSIVE","policyname":"Users delete tenant templates","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"estimate_templates","permissive":"PERMISSIVE","policyname":"Users update tenant templates","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"estimate_templates","permissive":"PERMISSIVE","policyname":"Users view tenant templates","schemaname":"public","with_check":null}],"triggers":[{"name":"estimate_templates_updated_at","definition":"CREATE TRIGGER estimate_templates_updated_at BEFORE UPDATE ON estimate_templates FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"estimate_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"event_bookings","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"venue_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":"'other'::text","identity":"","not_null":true,"generated":""},{"name":"stage","type":"text","default":"'Inquiry'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"event_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"start_time","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"end_time","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"location","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"guest_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"pricing_basis","type":"text","default":"'flat_event'::text","identity":"","not_null":true,"generated":""},{"name":"service_unit_label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"quoted_units","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"served_units","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"setup","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_package","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"quote_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"deposit_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"balance_due","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"staffing","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"requirements","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"loadout","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"expenses","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_intake","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"confirmed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"event_bookings_contact_idx","definition":"CREATE INDEX event_bookings_contact_idx ON public.event_bookings USING btree (contact_id)"},{"name":"event_bookings_pkey","definition":"CREATE UNIQUE INDEX event_bookings_pkey ON public.event_bookings USING btree (id)"},{"name":"event_bookings_source_ref_uq","definition":"CREATE UNIQUE INDEX event_bookings_source_ref_uq ON public.event_bookings USING btree (tenant_org_id, source, source_ref) WHERE (source_ref IS NOT NULL)"},{"name":"event_bookings_tenant_date_idx","definition":"CREATE INDEX event_bookings_tenant_date_idx ON public.event_bookings USING btree (tenant_org_id, event_date)"},{"name":"event_bookings_tenant_stage_idx","definition":"CREATE INDEX event_bookings_tenant_stage_idx ON public.event_bookings USING btree (tenant_org_id, stage)"},{"name":"event_bookings_tenant_start_idx","definition":"CREATE INDEX event_bookings_tenant_start_idx ON public.event_bookings USING btree (tenant_org_id, start_time)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"event_bookings","permissive":"PERMISSIVE","policyname":"event_bookings_tenant_access","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"}],"triggers":[{"name":"sync_mobile_vendor_event_expenses_to_finance_trigger","definition":"CREATE TRIGGER sync_mobile_vendor_event_expenses_to_finance_trigger AFTER INSERT OR UPDATE OF expenses, event_date, event_name ON event_bookings FOR EACH ROW EXECUTE FUNCTION sync_mobile_vendor_event_expenses_to_finance()"}],"constraints":[{"name":"event_bookings_amounts_nonnegative","definition":"CHECK ((quote_amount IS NULL OR quote_amount >= 0::numeric) AND (deposit_amount IS NULL OR deposit_amount >= 0::numeric) AND (balance_due IS NULL OR balance_due >= 0::numeric))"},{"name":"event_bookings_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"event_bookings_guest_count_nonnegative","definition":"CHECK (guest_count IS NULL OR guest_count >= 0)"},{"name":"event_bookings_pkey","definition":"PRIMARY KEY (id)"},{"name":"event_bookings_service_units_nonnegative","definition":"CHECK ((quoted_units IS NULL OR quoted_units >= 0) AND (served_units IS NULL OR served_units >= 0))"}]},{"table":"event_workflow_steps","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"phase","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"step_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"event_workflow_steps_event_booking_id_step_key_key","definition":"CREATE UNIQUE INDEX event_workflow_steps_event_booking_id_step_key_key ON public.event_workflow_steps USING btree (event_booking_id, step_key)"},{"name":"event_workflow_steps_event_idx","definition":"CREATE INDEX event_workflow_steps_event_idx ON public.event_workflow_steps USING btree (event_booking_id, sort_order)"},{"name":"event_workflow_steps_pkey","definition":"CREATE UNIQUE INDEX event_workflow_steps_pkey ON public.event_workflow_steps USING btree (id)"},{"name":"event_workflow_steps_tenant_status_idx","definition":"CREATE INDEX event_workflow_steps_tenant_status_idx ON public.event_workflow_steps USING btree (tenant_org_id, status)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"event_workflow_steps","permissive":"PERMISSIVE","policyname":"event_workflow_steps_tenant_access","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"}],"triggers":[],"constraints":[{"name":"event_workflow_steps_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE CASCADE"},{"name":"event_workflow_steps_event_booking_id_step_key_key","definition":"UNIQUE (event_booking_id, step_key)"},{"name":"event_workflow_steps_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"experience_preview_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"projected_role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"surface_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"route","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"device","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"version_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parent_origin","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"validated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"experience_preview_sessions_expiry_idx","definition":"CREATE INDEX experience_preview_sessions_expiry_idx ON public.experience_preview_sessions USING btree (expires_at)"},{"name":"experience_preview_sessions_pkey","definition":"CREATE UNIQUE INDEX experience_preview_sessions_pkey ON public.experience_preview_sessions USING btree (id)"},{"name":"experience_preview_sessions_token_hash_key","definition":"CREATE UNIQUE INDEX experience_preview_sessions_token_hash_key ON public.experience_preview_sessions USING btree (token_hash)"},{"name":"experience_preview_sessions_user_tenant_idx","definition":"CREATE INDEX experience_preview_sessions_user_tenant_idx ON public.experience_preview_sessions USING btree (user_id, tenant_id, expires_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"experience_preview_sessions_device_check","definition":"CHECK (device = ANY (ARRAY['desktop'::text, 'tablet'::text, 'mobile'::text]))"},{"name":"experience_preview_sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"experience_preview_sessions_projected_role_check","definition":"CHECK (projected_role = ANY (ARRAY['Owner'::text, 'Manager'::text, 'Operator'::text, 'Field'::text]))"},{"name":"experience_preview_sessions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"experience_preview_sessions_token_hash_key","definition":"UNIQUE (token_hash)"},{"name":"experience_preview_sessions_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"feature_entitlement_audit_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"feature_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"previous_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"previous_effective_access","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_effective_access","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"feature_entitlement_audit_log_pkey","definition":"CREATE UNIQUE INDEX feature_entitlement_audit_log_pkey ON public.feature_entitlement_audit_log USING btree (id)"},{"name":"idx_feal_created","definition":"CREATE INDEX idx_feal_created ON public.feature_entitlement_audit_log USING btree (created_at DESC)"},{"name":"idx_feal_feature","definition":"CREATE INDEX idx_feal_feature ON public.feature_entitlement_audit_log USING btree (feature_key)"},{"name":"idx_feal_tenant","definition":"CREATE INDEX idx_feal_tenant ON public.feature_entitlement_audit_log USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"feature_entitlement_audit_log","permissive":"PERMISSIVE","policyname":"feal system admin insert","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"feature_entitlement_audit_log","permissive":"PERMISSIVE","policyname":"feal system admin read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"feature_entitlement_audit_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"feature_flags","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"flag_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"enabled","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'experimental'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rollout_percentage","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"feature_flags_flag_key_tenant_id_key","definition":"CREATE UNIQUE INDEX feature_flags_flag_key_tenant_id_key ON public.feature_flags USING btree (flag_key, tenant_id)"},{"name":"feature_flags_pkey","definition":"CREATE UNIQUE INDEX feature_flags_pkey ON public.feature_flags USING btree (id)"},{"name":"idx_feature_flags_key","definition":"CREATE INDEX idx_feature_flags_key ON public.feature_flags USING btree (flag_key)"},{"name":"idx_feature_flags_tenant","definition":"CREATE INDEX idx_feature_flags_tenant ON public.feature_flags USING btree (tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"feature_flags","permissive":"PERMISSIVE","policyname":"Authenticated can read feature flags","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_platform_admin(uid())","roles":["authenticated"],"tablename":"feature_flags","permissive":"PERMISSIVE","policyname":"Platform admins can manage feature flags","schemaname":"public","with_check":"is_platform_admin(uid())"}],"triggers":[{"name":"trg_feature_flags_updated_at","definition":"CREATE TRIGGER trg_feature_flags_updated_at BEFORE UPDATE ON feature_flags FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"feature_flags_flag_key_tenant_id_key","definition":"UNIQUE (flag_key, tenant_id)"},{"name":"feature_flags_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"feature_permissions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"feature_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"granted_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"granted_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"feature_permissions_pkey","definition":"CREATE UNIQUE INDEX feature_permissions_pkey ON public.feature_permissions USING btree (id)"},{"name":"feature_permissions_user_tenant_feature_uniq","definition":"CREATE UNIQUE INDEX feature_permissions_user_tenant_feature_uniq ON public.feature_permissions USING btree (user_id, COALESCE(tenant_id, '00000000-0000-0000-0000-000000000000'::uuid), feature_name)"},{"name":"idx_feature_permissions_user_feature","definition":"CREATE INDEX idx_feature_permissions_user_feature ON public.feature_permissions USING btree (user_id, feature_name)"}],"policies":[{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = feature_permissions.tenant_id) AND (m.is_owner = true) AND (m.status = 'active'::text)))))","roles":["authenticated"],"tablename":"feature_permissions","permissive":"PERMISSIVE","policyname":"Tenant owners manage feature permissions in their tenant","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = feature_permissions.tenant_id) AND (m.is_owner = true) AND (m.status = 'active'::text)))))"},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"feature_permissions","permissive":"PERMISSIVE","policyname":"Users view own permissions","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"feature_permissions","permissive":"PERMISSIVE","policyname":"platform_admin_manage_feature_permissions","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"feature_permissions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"feature_preview_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"feature_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"feature_preview_log_pkey","definition":"CREATE UNIQUE INDEX feature_preview_log_pkey ON public.feature_preview_log USING btree (id)"},{"name":"idx_feature_preview_log_tenant","definition":"CREATE INDEX idx_feature_preview_log_tenant ON public.feature_preview_log USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"feature_preview_log","permissive":"PERMISSIVE","policyname":"Authenticated users log their own preview events","schemaname":"public","with_check":"((uid() IS NOT NULL) AND ((user_id IS NULL) OR (user_id = uid())))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = feature_preview_log.tenant_id) AND (m.status = 'active'::text)))))","roles":["public"],"tablename":"feature_preview_log","permissive":"PERMISSIVE","policyname":"Tenant members and admins read preview log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"feature_preview_log_action_check","definition":"CHECK (action = ANY (ARRAY['view_blurred'::text, 'click_locked'::text, 'hover_upgrade'::text, 'open_upgrade_modal'::text, 'dismiss_upgrade'::text]))"},{"name":"feature_preview_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"finance_accounts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"external_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"institution_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"account_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"account_subtype","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last4","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"last_synced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"finance_accounts_pkey","definition":"CREATE UNIQUE INDEX finance_accounts_pkey ON public.finance_accounts USING btree (id)"},{"name":"finance_accounts_tenant_idx","definition":"CREATE INDEX finance_accounts_tenant_idx ON public.finance_accounts USING btree (tenant_id, provider, status)"},{"name":"finance_accounts_tenant_provider_external_key","definition":"CREATE UNIQUE INDEX finance_accounts_tenant_provider_external_key ON public.finance_accounts USING btree (tenant_id, provider, external_id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = finance_accounts.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))))","roles":["public"],"tablename":"finance_accounts","permissive":"PERMISSIVE","policyname":"finance_accounts_tenant_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = finance_accounts.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))))","roles":["public"],"tablename":"finance_accounts","permissive":"PERMISSIVE","policyname":"finance_accounts_tenant_write","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = finance_accounts.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"finance_accounts_pkey","definition":"PRIMARY KEY (id)"},{"name":"finance_accounts_provider_check","definition":"CHECK (provider = ANY (ARRAY['stripe'::text, 'stripe_financial_connections'::text, 'manual'::text, 'import'::text]))"},{"name":"finance_accounts_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'pending'::text, 'disconnected'::text, 'error'::text]))"},{"name":"finance_accounts_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"finance_accounts_tenant_provider_external_key","definition":"UNIQUE (tenant_id, provider, external_id)"}]},{"table":"finance_report_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"scheduled_report_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"period_start","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_end","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'generating'::text","identity":"","not_null":true,"generated":""},{"name":"storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recipients","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"recipient_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"totals","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"finance_report_runs_pkey","definition":"CREATE UNIQUE INDEX finance_report_runs_pkey ON public.finance_report_runs USING btree (id)"},{"name":"finance_report_runs_schedule_created_idx","definition":"CREATE INDEX finance_report_runs_schedule_created_idx ON public.finance_report_runs USING btree (scheduled_report_id, created_at DESC) WHERE (scheduled_report_id IS NOT NULL)"},{"name":"finance_report_runs_tenant_created_idx","definition":"CREATE INDEX finance_report_runs_tenant_created_idx ON public.finance_report_runs USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = finance_report_runs.tenant_id) AND (COALESCE(membership.status, 'active'::text) = 'active'::text)))))","roles":["public"],"tablename":"finance_report_runs","permissive":"PERMISSIVE","policyname":"finance_report_runs_tenant_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"finance_report_runs_period_check","definition":"CHECK (period_end >= period_start)"},{"name":"finance_report_runs_pkey","definition":"PRIMARY KEY (id)"},{"name":"finance_report_runs_recipient_count_check","definition":"CHECK (recipient_count >= 0)"},{"name":"finance_report_runs_scheduled_report_id_fkey","definition":"FOREIGN KEY (scheduled_report_id) REFERENCES scheduled_reports(id) ON DELETE SET NULL"},{"name":"finance_report_runs_status_check","definition":"CHECK (status = ANY (ARRAY['generating'::text, 'generated'::text, 'queued'::text, 'sent'::text, 'failed'::text]))"},{"name":"finance_report_runs_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"finance_transactions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"account_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_external_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transaction_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"posted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"merchant","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"amount","type":"numeric(14,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"direction","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"transaction_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":"'Uncategorized'::text","identity":"","not_null":true,"generated":""},{"name":"classification","type":"text","default":"'review'::text","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"receipt_document_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"finance_transactions_pkey","definition":"CREATE UNIQUE INDEX finance_transactions_pkey ON public.finance_transactions USING btree (id)"},{"name":"finance_transactions_tenant_category_idx","definition":"CREATE INDEX finance_transactions_tenant_category_idx ON public.finance_transactions USING btree (tenant_id, category, transaction_date DESC)"},{"name":"finance_transactions_tenant_date_idx","definition":"CREATE INDEX finance_transactions_tenant_date_idx ON public.finance_transactions USING btree (tenant_id, transaction_date DESC)"},{"name":"finance_transactions_tenant_review_idx","definition":"CREATE INDEX finance_transactions_tenant_review_idx ON public.finance_transactions USING btree (tenant_id, classification, transaction_date DESC)"},{"name":"finance_transactions_tenant_source_external_key","definition":"CREATE UNIQUE INDEX finance_transactions_tenant_source_external_key ON public.finance_transactions USING btree (tenant_id, source, provider_external_id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = finance_transactions.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))))","roles":["public"],"tablename":"finance_transactions","permissive":"PERMISSIVE","policyname":"finance_transactions_tenant_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = finance_transactions.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))))","roles":["public"],"tablename":"finance_transactions","permissive":"PERMISSIVE","policyname":"finance_transactions_tenant_write","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = finance_transactions.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"finance_transactions_account_id_fkey","definition":"FOREIGN KEY (account_id) REFERENCES finance_accounts(id) ON DELETE SET NULL"},{"name":"finance_transactions_amount_check","definition":"CHECK (amount >= 0::numeric)"},{"name":"finance_transactions_classification_check","definition":"CHECK (classification = ANY (ARRAY['business'::text, 'personal'::text, 'review'::text]))"},{"name":"finance_transactions_direction_check","definition":"CHECK (direction = ANY (ARRAY['income'::text, 'expense'::text]))"},{"name":"finance_transactions_pkey","definition":"PRIMARY KEY (id)"},{"name":"finance_transactions_source_check","definition":"CHECK (source ~ '^[a-z0-9][a-z0-9_]{1,63}$'::text)"},{"name":"finance_transactions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"finance_transactions_tenant_source_external_key","definition":"UNIQUE (tenant_id, source, provider_external_id)"}]},{"table":"florida_jurisdictions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"jurisdiction_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"county","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"region","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"portal_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"portal_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"portal_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adapter_status","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"adapter_class","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"edge_function_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"supports_roof_permits","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"supports_all_permits","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"data_quality_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"population","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority","type":"integer","default":"50","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"florida_jurisdictions_jurisdiction_key_key","definition":"CREATE UNIQUE INDEX florida_jurisdictions_jurisdiction_key_key ON public.florida_jurisdictions USING btree (jurisdiction_key)"},{"name":"florida_jurisdictions_pkey","definition":"CREATE UNIQUE INDEX florida_jurisdictions_pkey ON public.florida_jurisdictions USING btree (id)"},{"name":"idx_florida_jurisdictions_adapter_status","definition":"CREATE INDEX idx_florida_jurisdictions_adapter_status ON public.florida_jurisdictions USING btree (adapter_status)"},{"name":"idx_florida_jurisdictions_county","definition":"CREATE INDEX idx_florida_jurisdictions_county ON public.florida_jurisdictions USING btree (county)"},{"name":"idx_florida_jurisdictions_portal_type","definition":"CREATE INDEX idx_florida_jurisdictions_portal_type ON public.florida_jurisdictions USING btree (portal_type)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["public"],"tablename":"florida_jurisdictions","permissive":"PERMISSIVE","policyname":"Anyone can read jurisdiction data","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"florida_jurisdictions","permissive":"PERMISSIVE","policyname":"System admins can modify jurisdiction data","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"update_florida_jurisdictions_updated_at","definition":"CREATE TRIGGER update_florida_jurisdictions_updated_at BEFORE UPDATE ON florida_jurisdictions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"florida_jurisdictions_adapter_status_check","definition":"CHECK (adapter_status = ANY (ARRAY['not_started'::text, 'in_progress'::text, 'active'::text, 'deprecated'::text, 'blocked'::text]))"},{"name":"florida_jurisdictions_jurisdiction_key_key","definition":"UNIQUE (jurisdiction_key)"},{"name":"florida_jurisdictions_jurisdiction_type_check","definition":"CHECK (jurisdiction_type = ANY (ARRAY['county'::text, 'city'::text, 'town'::text, 'village'::text, 'special_district'::text]))"},{"name":"florida_jurisdictions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"foil_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"municipality","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"request_status","type":"text","default":"'not_requested'::text","identity":"","not_null":true,"generated":""},{"name":"request_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"response_due_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"response_received_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"records_requested","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"records_received_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"foil_requests_pkey","definition":"CREATE UNIQUE INDEX foil_requests_pkey ON public.foil_requests USING btree (id)"},{"name":"idx_foil_property","definition":"CREATE INDEX idx_foil_property ON public.foil_requests USING btree (property_id)"},{"name":"idx_foil_status","definition":"CREATE INDEX idx_foil_status ON public.foil_requests USING btree (request_status)"},{"name":"idx_foil_tenant","definition":"CREATE INDEX idx_foil_tenant ON public.foil_requests USING btree (tenant_org_id)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"foil_requests","permissive":"PERMISSIVE","policyname":"foil_delete_tenant_members","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"foil_requests","permissive":"PERMISSIVE","policyname":"foil_insert_tenant_members","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"foil_requests","permissive":"PERMISSIVE","policyname":"foil_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"foil_requests","permissive":"PERMISSIVE","policyname":"foil_update_tenant_members","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_foil_updated_at","definition":"CREATE TRIGGER trg_foil_updated_at BEFORE UPDATE ON foil_requests FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"foil_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"foil_requests_request_status_check","definition":"CHECK (request_status = ANY (ARRAY['not_requested'::text, 'drafted'::text, 'submitted'::text, 'received'::text, 'denied'::text, 'archived'::text]))"}]},{"table":"followups","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"followup_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'Pending'::text","identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"followups_pkey","definition":"CREATE UNIQUE INDEX followups_pkey ON public.followups USING btree (id)"},{"name":"idx_followups_date","definition":"CREATE INDEX idx_followups_date ON public.followups USING btree (followup_date)"},{"name":"idx_followups_rep","definition":"CREATE INDEX idx_followups_rep ON public.followups USING btree (rep_email)"}],"policies":[{"cmd":"ALL","qual":"(rep_email = ( SELECT profiles.email\n   FROM profiles\n  WHERE (profiles.id = uid())))","roles":["public"],"tablename":"followups","permissive":"PERMISSIVE","policyname":"Users manage own followups","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(rep_email = ( SELECT profiles.email\n   FROM profiles\n  WHERE (profiles.id = uid())))","roles":["public"],"tablename":"followups","permissive":"PERMISSIVE","policyname":"Users view own followups","schemaname":"public","with_check":null}],"triggers":[{"name":"audit_trigger_followups","definition":"CREATE TRIGGER audit_trigger_followups AFTER INSERT OR DELETE OR UPDATE ON followups FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"}],"constraints":[{"name":"followups_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"funnel_snapshots","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"funnel_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"snapshot_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_data","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"total_leads","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"total_converted","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"overall_conversion_rate","type":"numeric(5,2)","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"funnel_snapshots_pkey","definition":"CREATE UNIQUE INDEX funnel_snapshots_pkey ON public.funnel_snapshots USING btree (id)"},{"name":"idx_funnel_snapshots_date","definition":"CREATE INDEX idx_funnel_snapshots_date ON public.funnel_snapshots USING btree (snapshot_date)"},{"name":"idx_funnel_snapshots_funnel","definition":"CREATE INDEX idx_funnel_snapshots_funnel ON public.funnel_snapshots USING btree (funnel_id)"}],"policies":[{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"funnel_snapshots","permissive":"PERMISSIVE","policyname":"Users can view own tenant funnel snapshots","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"funnel_snapshots_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"godmode_page_overrides","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"route_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"route_pattern","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_scope","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"device_scope","type":"text","default":"'all'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":"'Untitled Shell Studio override'::text","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"operations","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"published_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"published_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"godmode_page_overrides_pkey","definition":"CREATE UNIQUE INDEX godmode_page_overrides_pkey ON public.godmode_page_overrides USING btree (id)"},{"name":"godmode_page_overrides_route_status_idx","definition":"CREATE INDEX godmode_page_overrides_route_status_idx ON public.godmode_page_overrides USING btree (route_path, status, device_scope)"}],"policies":[{"cmd":"ALL","qual":"is_platform_admin(request_user_id())","roles":["authenticated"],"tablename":"godmode_page_overrides","permissive":"PERMISSIVE","policyname":"godmode_page_overrides_platform_admin_manage","schemaname":"public","with_check":"is_platform_admin(request_user_id())"},{"cmd":"SELECT","qual":"(status = 'published'::text)","roles":["public"],"tablename":"godmode_page_overrides","permissive":"PERMISSIVE","policyname":"godmode_page_overrides_published_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"can_manage_page_override(request_user_id(), tenant_scope)","roles":["authenticated"],"tablename":"godmode_page_overrides","permissive":"PERMISSIVE","policyname":"godmode_page_overrides_tenant_manage","schemaname":"public","with_check":"can_manage_page_override(request_user_id(), tenant_scope)"}],"triggers":[],"constraints":[{"name":"godmode_page_overrides_device_scope_check","definition":"CHECK (device_scope = ANY (ARRAY['all'::text, 'desktop'::text, 'mobile'::text]))"},{"name":"godmode_page_overrides_pkey","definition":"PRIMARY KEY (id)"},{"name":"godmode_page_overrides_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'published'::text, 'archived'::text]))"}]},{"table":"hail_swaths","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"event_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"bbox_minlat","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"bbox_minlng","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"bbox_maxlat","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"bbox_maxlng","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"max_hail_inches","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"cells_geojson","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"cell_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'mrms_mesh'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"hail_swaths_pkey","definition":"CREATE UNIQUE INDEX hail_swaths_pkey ON public.hail_swaths USING btree (id)"},{"name":"idx_hail_swaths_bbox","definition":"CREATE INDEX idx_hail_swaths_bbox ON public.hail_swaths USING btree (bbox_minlat, bbox_maxlat, bbox_minlng, bbox_maxlng)"},{"name":"idx_hail_swaths_dedupe","definition":"CREATE UNIQUE INDEX idx_hail_swaths_dedupe ON public.hail_swaths USING btree (event_date, bbox_minlat, bbox_minlng, bbox_maxlat, bbox_maxlng, source)"},{"name":"idx_hail_swaths_event_date","definition":"CREATE INDEX idx_hail_swaths_event_date ON public.hail_swaths USING btree (event_date DESC)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"hail_swaths","permissive":"PERMISSIVE","policyname":"Authenticated users can read hail swaths","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"hail_swaths_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"homeowner_financing_prequals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"credit_tier","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"annual_income","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_amount","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"term_months","type":"integer","default":"120","identity":"","not_null":true,"generated":""},{"name":"estimated_apr","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"monthly_payment","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"approval_likelihood","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lender_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_reference","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"homeowner_financing_prequals_pkey","definition":"CREATE UNIQUE INDEX homeowner_financing_prequals_pkey ON public.homeowner_financing_prequals USING btree (id)"},{"name":"idx_financing_prequals_contact","definition":"CREATE INDEX idx_financing_prequals_contact ON public.homeowner_financing_prequals USING btree (contact_id)"},{"name":"idx_financing_prequals_tenant","definition":"CREATE INDEX idx_financing_prequals_tenant ON public.homeowner_financing_prequals USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"homeowner_financing_prequals","permissive":"PERMISSIVE","policyname":"Tenant members create financing prequals","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text))))"},{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text))))","roles":["public"],"tablename":"homeowner_financing_prequals","permissive":"PERMISSIVE","policyname":"Tenant members delete financing prequals","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text))))","roles":["public"],"tablename":"homeowner_financing_prequals","permissive":"PERMISSIVE","policyname":"Tenant members update financing prequals","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text))))","roles":["public"],"tablename":"homeowner_financing_prequals","permissive":"PERMISSIVE","policyname":"Tenant members view financing prequals","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_financing_prequals_updated_at","definition":"CREATE TRIGGER trg_financing_prequals_updated_at BEFORE UPDATE ON homeowner_financing_prequals FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"homeowner_financing_prequals_approval_likelihood_check","definition":"CHECK (approval_likelihood = ANY (ARRAY['high'::text, 'medium'::text, 'low'::text]))"},{"name":"homeowner_financing_prequals_credit_tier_check","definition":"CHECK (credit_tier = ANY (ARRAY['excellent'::text, 'good'::text, 'fair'::text, 'poor'::text]))"},{"name":"homeowner_financing_prequals_pkey","definition":"PRIMARY KEY (id)"},{"name":"homeowner_financing_prequals_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'submitted'::text, 'approved'::text, 'declined'::text, 'funded'::text]))"}]},{"table":"homeowner_stage_messages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"vertical","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"pipeline_kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body_md","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_milestone","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"send_to_homeowner","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"homeowner_stage_messages_pkey","definition":"CREATE UNIQUE INDEX homeowner_stage_messages_pkey ON public.homeowner_stage_messages USING btree (id)"},{"name":"homeowner_stage_messages_tenant_org_id_vertical_pipeline_ki_key","definition":"CREATE UNIQUE INDEX homeowner_stage_messages_tenant_org_id_vertical_pipeline_ki_key ON public.homeowner_stage_messages USING btree (tenant_org_id, vertical, pipeline_kind, stage_name)"},{"name":"idx_hsm_lookup","definition":"CREATE INDEX idx_hsm_lookup ON public.homeowner_stage_messages USING btree (vertical, pipeline_kind, stage_name) WHERE (send_to_homeowner = true)"},{"name":"idx_hsm_tenant","definition":"CREATE INDEX idx_hsm_tenant ON public.homeowner_stage_messages USING btree (tenant_org_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"homeowner_stage_messages","permissive":"PERMISSIVE","policyname":"hsm_godmode_manage","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"homeowner_stage_messages","permissive":"PERMISSIVE","policyname":"hsm_read_defaults_or_tenant","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_org_id))","roles":["public"],"tablename":"homeowner_stage_messages","permissive":"PERMISSIVE","policyname":"hsm_tenant_owner_manage","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_org_id))"}],"triggers":[{"name":"trg_hsm_updated_at","definition":"CREATE TRIGGER trg_hsm_updated_at BEFORE UPDATE ON homeowner_stage_messages FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"homeowner_stage_messages_pipeline_kind_check","definition":"CHECK (pipeline_kind = ANY (ARRAY['LEAD'::text, 'CLAIM'::text, 'JOB'::text]))"},{"name":"homeowner_stage_messages_pkey","definition":"PRIMARY KEY (id)"},{"name":"homeowner_stage_messages_tenant_org_id_vertical_pipeline_ki_key","definition":"UNIQUE (tenant_org_id, vertical, pipeline_kind, stage_name)"},{"name":"homeowner_stage_messages_vertical_check","definition":"CHECK (vertical = ANY (ARRAY['public_adjuster'::text, 'roofer'::text, 'mitigation'::text, 'realtor'::text, 'universal'::text]))"}]},{"table":"ims_logs","schema":"public","columns":[{"name":"id","type":"bigint","default":"nextval('ims_logs_id_seq'::regclass)","identity":"","not_null":true,"generated":""},{"name":"ts","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"op","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"ok","type":"boolean","default":null,"identity":"","not_null":true,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"extra","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"ims_logs_pkey","definition":"CREATE UNIQUE INDEX ims_logs_pkey ON public.ims_logs USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"ims_logs","permissive":"PERMISSIVE","policyname":"ims_logs_insert","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = ims_logs.tenant_id)))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = ims_logs.tenant_id)))))","roles":["authenticated"],"tablename":"ims_logs","permissive":"PERMISSIVE","policyname":"ims_logs_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"ims_logs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ims_sessions","schema":"public","columns":[{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"cookie","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"refreshed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"meta","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ims_sessions_pkey","definition":"CREATE UNIQUE INDEX ims_sessions_pkey ON public.ims_sessions USING btree (tenant_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"ims_sessions","permissive":"PERMISSIVE","policyname":"ims_sessions_insert","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = ims_sessions.tenant_id)))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = ur.user_id) AND (m.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = ims_sessions.tenant_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"ims_sessions","permissive":"PERMISSIVE","policyname":"ims_sessions_select_owner_admin","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = ims_sessions.tenant_id)))))","roles":["authenticated"],"tablename":"ims_sessions","permissive":"PERMISSIVE","policyname":"ims_sessions_update","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = ims_sessions.tenant_id)))))"}],"triggers":[],"constraints":[{"name":"ims_sessions_pkey","definition":"PRIMARY KEY (tenant_id)"}]},{"table":"inbound_call_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_number_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"direction","type":"text","default":"'inbound'::text","identity":"","not_null":true,"generated":""},{"name":"call_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_transcription","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"forwarded_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_inbound_call_logs_tenant","definition":"CREATE INDEX idx_inbound_call_logs_tenant ON public.inbound_call_logs USING btree (tenant_org_id)"},{"name":"idx_inbound_call_logs_to","definition":"CREATE INDEX idx_inbound_call_logs_to ON public.inbound_call_logs USING btree (to_number)"},{"name":"idx_inbound_call_logs_user","definition":"CREATE INDEX idx_inbound_call_logs_user ON public.inbound_call_logs USING btree (assigned_user_id)"},{"name":"inbound_call_logs_pkey","definition":"CREATE UNIQUE INDEX inbound_call_logs_pkey ON public.inbound_call_logs USING btree (id)"},{"name":"inbound_call_logs_twilio_call_sid_key","definition":"CREATE UNIQUE INDEX inbound_call_logs_twilio_call_sid_key ON public.inbound_call_logs USING btree (twilio_call_sid)"}],"policies":[{"cmd":"SELECT","qual":"(assigned_user_id = uid())","roles":["authenticated"],"tablename":"inbound_call_logs","permissive":"PERMISSIVE","policyname":"Reps view their own inbound calls","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id, uid())","roles":["authenticated"],"tablename":"inbound_call_logs","permissive":"PERMISSIVE","policyname":"Tenant owners view all inbound calls","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_owner_capture_unknown_inbound_call_contact","definition":"CREATE TRIGGER trg_owner_capture_unknown_inbound_call_contact BEFORE INSERT ON inbound_call_logs FOR EACH ROW EXECUTE FUNCTION owner_capture_unknown_inbound_call_contact()"},{"name":"update_inbound_call_logs_updated_at","definition":"CREATE TRIGGER update_inbound_call_logs_updated_at BEFORE UPDATE ON inbound_call_logs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"inbound_call_logs_pkey","definition":"PRIMARY KEY (id)"},{"name":"inbound_call_logs_twilio_call_sid_key","definition":"UNIQUE (twilio_call_sid)"}]},{"table":"inbound_email_signals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider","type":"text","default":"'provider_agnostic'::text","identity":"","not_null":true,"generated":""},{"name":"provider_message_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sender_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sender_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"received_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"classification","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"confidence","type":"numeric(5,4)","default":null,"identity":"","not_null":false,"generated":""},{"name":"extracted","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"attachments","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"proposed_actions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"safe_updates","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'review'::text","identity":"","not_null":true,"generated":""},{"name":"raw_metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"inbound_email_signals_pkey","definition":"CREATE UNIQUE INDEX inbound_email_signals_pkey ON public.inbound_email_signals USING btree (id)"},{"name":"inbound_email_signals_provider_message_uq","definition":"CREATE UNIQUE INDEX inbound_email_signals_provider_message_uq ON public.inbound_email_signals USING btree (tenant_org_id, provider, provider_message_id) WHERE (provider_message_id IS NOT NULL)"},{"name":"inbound_email_signals_review_idx","definition":"CREATE INDEX inbound_email_signals_review_idx ON public.inbound_email_signals USING btree (tenant_org_id, status, received_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"inbound_email_signals","permissive":"PERMISSIVE","policyname":"inbound_email_signals_tenant_access","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"}],"triggers":[{"name":"inbound_email_signals_materialize_owner_notes_tasks","definition":"CREATE TRIGGER inbound_email_signals_materialize_owner_notes_tasks AFTER INSERT OR UPDATE OF classification, status, proposed_actions, extracted, subject, sender_name, sender_email, provider, provider_message_id ON inbound_email_signals FOR EACH ROW EXECUTE FUNCTION materialize_owner_notes_tasks_from_email_signal()"}],"constraints":[{"name":"inbound_email_signals_confidence_range","definition":"CHECK (confidence IS NULL OR confidence >= 0::numeric AND confidence <= 1::numeric)"},{"name":"inbound_email_signals_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"inbound_email_signals_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"inbound_email_signals_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"inbound_integration_keys","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"key_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"key_prefix","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"allowed_sources","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_used_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_inbound_integration_keys_active","definition":"CREATE INDEX idx_inbound_integration_keys_active ON public.inbound_integration_keys USING btree (is_active) WHERE (is_active = true)"},{"name":"idx_inbound_integration_keys_tenant","definition":"CREATE INDEX idx_inbound_integration_keys_tenant ON public.inbound_integration_keys USING btree (tenant_org_id)"},{"name":"inbound_integration_keys_key_hash_key","definition":"CREATE UNIQUE INDEX inbound_integration_keys_key_hash_key ON public.inbound_integration_keys USING btree (key_hash)"},{"name":"inbound_integration_keys_pkey","definition":"CREATE UNIQUE INDEX inbound_integration_keys_pkey ON public.inbound_integration_keys USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin()","roles":["authenticated"],"tablename":"inbound_integration_keys","permissive":"PERMISSIVE","policyname":"GodMode can manage inbound integration keys","schemaname":"public","with_check":"is_system_admin()"}],"triggers":[],"constraints":[{"name":"inbound_integration_keys_key_hash_key","definition":"UNIQUE (key_hash)"},{"name":"inbound_integration_keys_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"inbound_routing_profiles","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"timezone","type":"text","default":"'America/New_York'::text","identity":"","not_null":true,"generated":""},{"name":"business_hours","type":"jsonb","default":"'{\"fri\": {\"open\": \"09:00\", \"close\": \"18:00\"}, \"mon\": {\"open\": \"09:00\", \"close\": \"18:00\"}, \"sat\": {\"closed\": true}, \"sun\": {\"closed\": true}, \"thu\": {\"open\": \"09:00\", \"close\": \"18:00\"}, \"tue\": {\"open\": \"09:00\", \"close\": \"18:00\"}, \"wed\": {\"open\": \"09:00\", \"close\": \"18:00\"}}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"caller_id_match_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"open_action","type":"text","default":"'ivr'::text","identity":"","not_null":true,"generated":""},{"name":"open_target_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"closed_action","type":"text","default":"'voicemail'::text","identity":"","not_null":true,"generated":""},{"name":"closed_target_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"closed_greeting","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_routing_profile_tenant","definition":"CREATE INDEX idx_routing_profile_tenant ON public.inbound_routing_profiles USING btree (tenant_org_id)"},{"name":"inbound_routing_profiles_pkey","definition":"CREATE UNIQUE INDEX inbound_routing_profiles_pkey ON public.inbound_routing_profiles USING btree (id)"},{"name":"uq_routing_profile_phone","definition":"CREATE UNIQUE INDEX uq_routing_profile_phone ON public.inbound_routing_profiles USING btree (phone_number) WHERE (phone_number IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"inbound_routing_profiles","permissive":"PERMISSIVE","policyname":"inbound_routing_profiles_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"inbound_routing_profiles","permissive":"PERMISSIVE","policyname":"inbound_routing_profiles_write_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_inbound_routing_profiles_updated_at","definition":"CREATE TRIGGER trg_inbound_routing_profiles_updated_at BEFORE UPDATE ON inbound_routing_profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"inbound_routing_profiles_closed_action_check","definition":"CHECK (closed_action = ANY (ARRAY['ivr'::text, 'ring_group'::text, 'voicemail'::text, 'hangup'::text]))"},{"name":"inbound_routing_profiles_open_action_check","definition":"CHECK (open_action = ANY (ARRAY['ivr'::text, 'ring_group'::text, 'voicemail'::text, 'hangup'::text]))"},{"name":"inbound_routing_profiles_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"inbound_sms_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_message_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"num_media","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"media_urls","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"forwarded_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_inbound_sms_logs_tenant","definition":"CREATE INDEX idx_inbound_sms_logs_tenant ON public.inbound_sms_logs USING btree (tenant_org_id)"},{"name":"idx_inbound_sms_logs_to","definition":"CREATE INDEX idx_inbound_sms_logs_to ON public.inbound_sms_logs USING btree (to_number)"},{"name":"idx_inbound_sms_logs_user","definition":"CREATE INDEX idx_inbound_sms_logs_user ON public.inbound_sms_logs USING btree (assigned_user_id)"},{"name":"inbound_sms_logs_pkey","definition":"CREATE UNIQUE INDEX inbound_sms_logs_pkey ON public.inbound_sms_logs USING btree (id)"},{"name":"inbound_sms_logs_twilio_message_sid_key","definition":"CREATE UNIQUE INDEX inbound_sms_logs_twilio_message_sid_key ON public.inbound_sms_logs USING btree (twilio_message_sid)"}],"policies":[{"cmd":"SELECT","qual":"(assigned_user_id = uid())","roles":["authenticated"],"tablename":"inbound_sms_logs","permissive":"PERMISSIVE","policyname":"Reps view their own inbound SMS","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id, uid())","roles":["authenticated"],"tablename":"inbound_sms_logs","permissive":"PERMISSIVE","policyname":"Tenant owners view all inbound SMS","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"inbound_sms_logs_pkey","definition":"PRIMARY KEY (id)"},{"name":"inbound_sms_logs_twilio_message_sid_key","definition":"UNIQUE (twilio_message_sid)"}]},{"table":"intelligence_briefs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"brief_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"window_start","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"window_end","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"health_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"headline","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sections_json","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"evidence_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"open_event_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"recommendation_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"generated_by_module","type":"text","default":"'intelligence-brief'::text","identity":"","not_null":true,"generated":""},{"name":"generated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"intelligence_briefs_latest_idx","definition":"CREATE INDEX intelligence_briefs_latest_idx ON public.intelligence_briefs USING btree (tenant_id, brief_type, generated_at DESC)"},{"name":"intelligence_briefs_pkey","definition":"CREATE UNIQUE INDEX intelligence_briefs_pkey ON public.intelligence_briefs USING btree (id)"},{"name":"intelligence_briefs_window_idx","definition":"CREATE INDEX intelligence_briefs_window_idx ON public.intelligence_briefs USING btree (tenant_id, window_start DESC, window_end DESC)"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"intelligence_briefs","permissive":"PERMISSIVE","policyname":"intelligence_briefs_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"intelligence_briefs_health_status_check","definition":"CHECK (health_status = ANY (ARRAY['green'::text, 'yellow'::text, 'red'::text, 'blocked'::text]))"},{"name":"intelligence_briefs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"intelligence_entity_context","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"context_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"facts_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"scores_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"recommendations_json","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"evidence_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"freshness_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"intelligence_entity_context_lookup_idx","definition":"CREATE INDEX intelligence_entity_context_lookup_idx ON public.intelligence_entity_context USING btree (tenant_id, entity_type, entity_id, context_type, freshness_at DESC)"},{"name":"intelligence_entity_context_pkey","definition":"CREATE UNIQUE INDEX intelligence_entity_context_pkey ON public.intelligence_entity_context USING btree (id)"},{"name":"intelligence_entity_context_type_idx","definition":"CREATE INDEX intelligence_entity_context_type_idx ON public.intelligence_entity_context USING btree (tenant_id, context_type, freshness_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"intelligence_entity_context","permissive":"PERMISSIVE","policyname":"intelligence_entity_context_select","schemaname":"public","with_check":null}],"triggers":[{"name":"intelligence_entity_context_touch","definition":"CREATE TRIGGER intelligence_entity_context_touch BEFORE UPDATE ON intelligence_entity_context FOR EACH ROW EXECUTE FUNCTION ai_touch_updated_at()"}],"constraints":[{"name":"intelligence_entity_context_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"intelligence_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"severity","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'open'::text","identity":"","not_null":true,"generated":""},{"name":"source_module","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_entity_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_entity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_job_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_storm_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"related_storm_zone_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"why_it_matters","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_action","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"evidence_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"confidence_score","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"dedupe_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"detected_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"intelligence_events_claim_idx","definition":"CREATE INDEX intelligence_events_claim_idx ON public.intelligence_events USING btree (related_claim_id) WHERE (related_claim_id IS NOT NULL)"},{"name":"intelligence_events_dedupe_idx","definition":"CREATE INDEX intelligence_events_dedupe_idx ON public.intelligence_events USING btree (tenant_id, dedupe_key) WHERE (dedupe_key IS NOT NULL)"},{"name":"intelligence_events_job_idx","definition":"CREATE INDEX intelligence_events_job_idx ON public.intelligence_events USING btree (related_job_id) WHERE (related_job_id IS NOT NULL)"},{"name":"intelligence_events_lead_idx","definition":"CREATE INDEX intelligence_events_lead_idx ON public.intelligence_events USING btree (related_lead_id) WHERE (related_lead_id IS NOT NULL)"},{"name":"intelligence_events_pkey","definition":"CREATE UNIQUE INDEX intelligence_events_pkey ON public.intelligence_events USING btree (id)"},{"name":"intelligence_events_storm_idx","definition":"CREATE INDEX intelligence_events_storm_idx ON public.intelligence_events USING btree (related_storm_id) WHERE (related_storm_id IS NOT NULL)"},{"name":"intelligence_events_storm_zone_idx","definition":"CREATE INDEX intelligence_events_storm_zone_idx ON public.intelligence_events USING btree (related_storm_zone_id) WHERE (related_storm_zone_id IS NOT NULL)"},{"name":"intelligence_events_tenant_status_idx","definition":"CREATE INDEX intelligence_events_tenant_status_idx ON public.intelligence_events USING btree (tenant_id, status, severity, detected_at DESC)"},{"name":"intelligence_events_tenant_type_idx","definition":"CREATE INDEX intelligence_events_tenant_type_idx ON public.intelligence_events USING btree (tenant_id, event_type, detected_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"intelligence_events","permissive":"PERMISSIVE","policyname":"intelligence_events_select","schemaname":"public","with_check":null}],"triggers":[{"name":"intelligence_events_materialize_business_opportunity","definition":"CREATE TRIGGER intelligence_events_materialize_business_opportunity AFTER INSERT ON intelligence_events FOR EACH ROW EXECUTE FUNCTION business_intelligence_event_after_insert()"},{"name":"intelligence_events_touch","definition":"CREATE TRIGGER intelligence_events_touch BEFORE UPDATE ON intelligence_events FOR EACH ROW EXECUTE FUNCTION ai_touch_updated_at()"}],"constraints":[{"name":"intelligence_events_confidence_score_check","definition":"CHECK (confidence_score IS NULL OR confidence_score >= 0::numeric AND confidence_score <= 1::numeric)"},{"name":"intelligence_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"intelligence_events_severity_check","definition":"CHECK (severity = ANY (ARRAY['info'::text, 'task'::text, 'urgent'::text, 'blocker'::text]))"},{"name":"intelligence_events_status_check","definition":"CHECK (status = ANY (ARRAY['open'::text, 'acknowledged'::text, 'dismissed'::text, 'resolved'::text, 'expired'::text]))"}]},{"table":"intelligence_recommendations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"recommendation_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"priority","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'open'::text","identity":"","not_null":true,"generated":""},{"name":"subject_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"why_it_matters","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"evidence_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"confidence_score","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"requires_human_review","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"requires_confirmation_before_write","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"allowed_action_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_from_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by_module","type":"text","default":"'intelligence'::text","identity":"","not_null":true,"generated":""},{"name":"accepted_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"accepted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"intelligence_recommendations_event_idx","definition":"CREATE INDEX intelligence_recommendations_event_idx ON public.intelligence_recommendations USING btree (created_from_event_id) WHERE (created_from_event_id IS NOT NULL)"},{"name":"intelligence_recommendations_open_idx","definition":"CREATE INDEX intelligence_recommendations_open_idx ON public.intelligence_recommendations USING btree (tenant_id, status, priority, created_at DESC)"},{"name":"intelligence_recommendations_pkey","definition":"CREATE UNIQUE INDEX intelligence_recommendations_pkey ON public.intelligence_recommendations USING btree (id)"},{"name":"intelligence_recommendations_subject_idx","definition":"CREATE INDEX intelligence_recommendations_subject_idx ON public.intelligence_recommendations USING btree (tenant_id, subject_type, subject_id, created_at DESC)"}],"policies":[{"cmd":"UPDATE","qual":"ai_is_tenant_admin(tenant_id)","roles":["authenticated"],"tablename":"intelligence_recommendations","permissive":"PERMISSIVE","policyname":"intelligence_recommendations_admin_update","schemaname":"public","with_check":"ai_is_tenant_admin(tenant_id)"},{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"intelligence_recommendations","permissive":"PERMISSIVE","policyname":"intelligence_recommendations_select","schemaname":"public","with_check":null}],"triggers":[{"name":"intelligence_recommendations_touch","definition":"CREATE TRIGGER intelligence_recommendations_touch BEFORE UPDATE ON intelligence_recommendations FOR EACH ROW EXECUTE FUNCTION ai_touch_updated_at()"}],"constraints":[{"name":"intelligence_recommendations_confidence_score_check","definition":"CHECK (confidence_score IS NULL OR confidence_score >= 0::numeric AND confidence_score <= 1::numeric)"},{"name":"intelligence_recommendations_created_from_event_id_fkey","definition":"FOREIGN KEY (created_from_event_id) REFERENCES intelligence_events(id) ON DELETE SET NULL"},{"name":"intelligence_recommendations_pkey","definition":"PRIMARY KEY (id)"},{"name":"intelligence_recommendations_priority_check","definition":"CHECK (priority = ANY (ARRAY['info'::text, 'task'::text, 'urgent'::text, 'blocker'::text]))"},{"name":"intelligence_recommendations_status_check","definition":"CHECK (status = ANY (ARRAY['open'::text, 'accepted'::text, 'dismissed'::text, 'completed'::text, 'expired'::text, 'superseded'::text]))"}]},{"table":"intelligence_source_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"module_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"run_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"window_start","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"window_end","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"input_summary","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"output_summary","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"intelligence_source_runs_module_idx","definition":"CREATE INDEX intelligence_source_runs_module_idx ON public.intelligence_source_runs USING btree (module_name, status, started_at DESC)"},{"name":"intelligence_source_runs_pkey","definition":"CREATE UNIQUE INDEX intelligence_source_runs_pkey ON public.intelligence_source_runs USING btree (id)"},{"name":"intelligence_source_runs_tenant_idx","definition":"CREATE INDEX intelligence_source_runs_tenant_idx ON public.intelligence_source_runs USING btree (tenant_id, started_at DESC) WHERE (tenant_id IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"((tenant_id IS NOT NULL) AND ai_is_tenant_admin(tenant_id))","roles":["authenticated"],"tablename":"intelligence_source_runs","permissive":"PERMISSIVE","policyname":"intelligence_source_runs_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"intelligence_source_runs_pkey","definition":"PRIMARY KEY (id)"},{"name":"intelligence_source_runs_status_check","definition":"CHECK (status = ANY (ARRAY['started'::text, 'completed'::text, 'failed'::text, 'skipped'::text]))"}]},{"table":"invoice_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variables","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_invoice_templates_tenant_key","definition":"CREATE INDEX idx_invoice_templates_tenant_key ON public.invoice_templates USING btree (tenant_id, key)"},{"name":"idx_invoice_templates_tone","definition":"CREATE INDEX idx_invoice_templates_tone ON public.invoice_templates USING btree (tone)"},{"name":"invoice_templates_pkey","definition":"CREATE UNIQUE INDEX invoice_templates_pkey ON public.invoice_templates USING btree (id)"},{"name":"invoice_templates_tenant_id_key_key","definition":"CREATE UNIQUE INDEX invoice_templates_tenant_id_key_key ON public.invoice_templates USING btree (tenant_id, key)"}],"policies":[{"cmd":"SELECT","qual":"((uid() IS NOT NULL) AND ((tenant_id IS NULL) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = invoice_templates.tenant_id))))))","roles":["public"],"tablename":"invoice_templates","permissive":"PERMISSIVE","policyname":"Authenticated users view global invoice templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"invoice_templates","permissive":"PERMISSIVE","policyname":"Tenant owners manage their invoice templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"invoice_templates","permissive":"PERMISSIVE","policyname":"invoice_templates_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_id IS NULL) OR is_tenant_member(uid(), tenant_id))","roles":["public"],"tablename":"invoice_templates","permissive":"PERMISSIVE","policyname":"invoice_templates_tenant_member_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_id))","roles":["public"],"tablename":"invoice_templates","permissive":"PERMISSIVE","policyname":"invoice_templates_tenant_owner_manage","schemaname":"public","with_check":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_id))"}],"triggers":[],"constraints":[{"name":"invoice_templates_body_not_blank","definition":"CHECK (length(btrim(body)) > 0)"},{"name":"invoice_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"invoice_templates_tenant_id_key_key","definition":"UNIQUE (tenant_id, key)"},{"name":"invoice_templates_tone_check","definition":"CHECK (tone = ANY (ARRAY['friendly'::text, 'standard'::text, 'stern'::text, 'vertical'::text]))"}]},{"table":"invoices","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"invoice_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"amount","type":"numeric(10,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'Draft'::text","identity":"","not_null":false,"generated":""},{"name":"due_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"line_items","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"subtotal","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"tax_rate","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"tax_amount","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"invoice_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_terms","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pdf_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pdf_file_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_provider_link_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_provider_order_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_provider_payment_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_provider_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"canonical_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_invoices_contact_id","definition":"CREATE INDEX idx_invoices_contact_id ON public.invoices USING btree (contact_id)"},{"name":"idx_invoices_invoice_date","definition":"CREATE INDEX idx_invoices_invoice_date ON public.invoices USING btree (invoice_date)"},{"name":"idx_invoices_status","definition":"CREATE INDEX idx_invoices_status ON public.invoices USING btree (status)"},{"name":"idx_invoices_tenant","definition":"CREATE INDEX idx_invoices_tenant ON public.invoices USING btree (tenant_org_id)"},{"name":"invoices_event_booking_idx","definition":"CREATE INDEX invoices_event_booking_idx ON public.invoices USING btree (event_booking_id)"},{"name":"invoices_invoice_id_key","definition":"CREATE UNIQUE INDEX invoices_invoice_id_key ON public.invoices USING btree (invoice_id)"},{"name":"invoices_pkey","definition":"CREATE UNIQUE INDEX invoices_pkey ON public.invoices USING btree (id)"},{"name":"invoices_square_order_lookup_idx","definition":"CREATE INDEX invoices_square_order_lookup_idx ON public.invoices USING btree (tenant_org_id, payment_provider, payment_provider_order_id) WHERE (payment_provider = 'square'::text)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships utm ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND ((utm.tenant_id)::text = invoices.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["public"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"Admins manage invoices","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships utm ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND ((utm.tenant_id)::text = invoices.tenant_org_id) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = invoices.tenant_org_id))))","roles":["public"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"Users view tenant invoices","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"inv_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"inv_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"inv_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"inv_update","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"tenant_users_delete_invoices","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"tenant_users_insert_invoices","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"tenant_users_update_invoices","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"invoices","permissive":"PERMISSIVE","policyname":"tenant_users_view_invoices","schemaname":"public","with_check":null}],"triggers":[{"name":"update_invoices_updated_at","definition":"CREATE TRIGGER update_invoices_updated_at BEFORE UPDATE ON invoices FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"invoices_canonical_contact_fkey","definition":"FOREIGN KEY (canonical_contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"invoices_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"invoices_invoice_id_key","definition":"UNIQUE (invoice_id)"},{"name":"invoices_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ivr_menus","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"greeting_text","type":"text","default":"'Thanks for calling. Please choose from the following options.'::text","identity":"","not_null":true,"generated":""},{"name":"greeting_audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice","type":"text","default":"'alice'::text","identity":"","not_null":true,"generated":""},{"name":"invalid_message","type":"text","default":"'Sorry, that is not a valid option.'::text","identity":"","not_null":true,"generated":""},{"name":"timeout_seconds","type":"smallint","default":"6","identity":"","not_null":true,"generated":""},{"name":"max_retries","type":"smallint","default":"2","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_ivr_menus_tenant","definition":"CREATE INDEX idx_ivr_menus_tenant ON public.ivr_menus USING btree (tenant_org_id)"},{"name":"ivr_menus_pkey","definition":"CREATE UNIQUE INDEX ivr_menus_pkey ON public.ivr_menus USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ivr_menus","permissive":"PERMISSIVE","policyname":"ivr_menus_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ivr_menus","permissive":"PERMISSIVE","policyname":"ivr_menus_write_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_ivr_menus_updated_at","definition":"CREATE TRIGGER trg_ivr_menus_updated_at BEFORE UPDATE ON ivr_menus FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"ivr_menus_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ivr_options","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"menu_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"digit","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"target_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sort_order","type":"smallint","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ivr_options_pkey","definition":"CREATE UNIQUE INDEX ivr_options_pkey ON public.ivr_options USING btree (id)"},{"name":"uq_ivr_option_per_menu_digit","definition":"CREATE UNIQUE INDEX uq_ivr_option_per_menu_digit ON public.ivr_options USING btree (menu_id, digit)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ivr_options","permissive":"PERMISSIVE","policyname":"ivr_options_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ivr_options","permissive":"PERMISSIVE","policyname":"ivr_options_write_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"}],"triggers":[],"constraints":[{"name":"ivr_options_action_check","definition":"CHECK (action = ANY (ARRAY['ring_group'::text, 'menu'::text, 'voicemail'::text, 'hangup'::text, 'external'::text]))"},{"name":"ivr_options_digit_check","definition":"CHECK (digit ~ '^[0-9*#]$'::text)"},{"name":"ivr_options_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_activity_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"activity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_job_activity_job","definition":"CREATE INDEX idx_job_activity_job ON public.job_activity_log USING btree (job_id, \"timestamp\" DESC)"},{"name":"idx_job_activity_tenant","definition":"CREATE INDEX idx_job_activity_tenant ON public.job_activity_log USING btree (tenant_id)"},{"name":"job_activity_log_pkey","definition":"CREATE UNIQUE INDEX job_activity_log_pkey ON public.job_activity_log USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"job_activity_log","permissive":"PERMISSIVE","policyname":"job_activity_insert_tenant_members","schemaname":"public","with_check":"(is_system_admin(uid()) OR is_tenant_member(uid(), tenant_id))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"job_activity_log","permissive":"PERMISSIVE","policyname":"job_activity_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"true","roles":["service_role"],"tablename":"job_activity_log","permissive":"PERMISSIVE","policyname":"job_activity_service_all","schemaname":"public","with_check":"true"}],"triggers":[{"name":"trg_job_activity_set_tenant","definition":"CREATE TRIGGER trg_job_activity_set_tenant BEFORE INSERT ON job_activity_log FOR EACH ROW EXECUTE FUNCTION job_activity_set_tenant()"}],"constraints":[{"name":"job_activity_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_photos","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"photo_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_url","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"uploaded_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"uploaded_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"caption","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_job_photos_job","definition":"CREATE INDEX idx_job_photos_job ON public.job_photos USING btree (job_id, uploaded_at DESC)"},{"name":"job_photos_pkey","definition":"CREATE UNIQUE INDEX job_photos_pkey ON public.job_photos USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"job_photos","permissive":"PERMISSIVE","policyname":"job_photos_insert_tenant_members","schemaname":"public","with_check":"(is_system_admin(uid()) OR is_tenant_member(uid(), tenant_id))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"job_photos","permissive":"PERMISSIVE","policyname":"job_photos_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"true","roles":["service_role"],"tablename":"job_photos","permissive":"PERMISSIVE","policyname":"job_photos_service_all","schemaname":"public","with_check":"true"}],"triggers":[{"name":"trg_job_photos_set_tenant","definition":"CREATE TRIGGER trg_job_photos_set_tenant BEFORE INSERT ON job_photos FOR EACH ROW EXECUTE FUNCTION job_photos_set_tenant()"}],"constraints":[{"name":"job_photos_photo_type_check","definition":"CHECK (photo_type = ANY (ARRAY['before'::text, 'during'::text, 'after'::text, 'damage'::text, 'completion'::text]))"},{"name":"job_photos_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_request_email_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"job_request_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":"'job_request_pending'::text","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'sent'::text","identity":"","not_null":true,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"job_request_email_log_pkey","definition":"CREATE UNIQUE INDEX job_request_email_log_pkey ON public.job_request_email_log USING btree (id)"},{"name":"job_request_email_log_unique","definition":"CREATE UNIQUE INDEX job_request_email_log_unique ON public.job_request_email_log USING btree (job_request_id, user_id, event_type)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM (job_requests jr\n     JOIN user_roles ur ON (((ur.tenant_id = jr.tenant_id) AND (ur.user_id = uid()) AND (ur.role = ANY (ARRAY['Manager'::app_role, 'Admin'::app_role, 'Tenant Owner'::app_role, 'Owner'::app_role])))))\n  WHERE (jr.id = job_request_email_log.job_request_id)))","roles":["authenticated"],"tablename":"job_request_email_log","permissive":"PERMISSIVE","policyname":"managers read job_request email log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"job_request_email_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_document_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_signed_agreement_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_kind","type":"text","default":"'manual'::text","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"requested_pm_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_crew_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scope","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority","type":"text","default":"'normal'::text","identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"photos_summary","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"job_request_status","default":"'pending_review'::job_request_status","identity":"","not_null":true,"generated":""},{"name":"reviewed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reject_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"converted_job_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_job_requests_contact","definition":"CREATE INDEX idx_job_requests_contact ON public.job_requests USING btree (contact_id)"},{"name":"idx_job_requests_tenant_status","definition":"CREATE INDEX idx_job_requests_tenant_status ON public.job_requests USING btree (tenant_id, status)"},{"name":"job_requests_pkey","definition":"CREATE UNIQUE INDEX job_requests_pkey ON public.job_requests USING btree (id)"},{"name":"job_requests_source_signed_agreement_id_key","definition":"CREATE UNIQUE INDEX job_requests_source_signed_agreement_id_key ON public.job_requests USING btree (source_signed_agreement_id)"}],"policies":[{"cmd":"DELETE","qual":"(is_manager_or_higher_strict(uid(), tenant_id) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"job_requests","permissive":"PERMISSIVE","policyname":"job_requests_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"job_requests","permissive":"PERMISSIVE","policyname":"job_requests_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_id) AND (created_by = uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"job_requests","permissive":"PERMISSIVE","policyname":"job_requests_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_manager_or_higher_strict(uid(), tenant_id) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"job_requests","permissive":"PERMISSIVE","policyname":"job_requests_update","schemaname":"public","with_check":"(is_manager_or_higher_strict(uid(), tenant_id) OR is_platform_admin(uid()))"}],"triggers":[{"name":"trg_enforce_job_request_state_machine","definition":"CREATE TRIGGER trg_enforce_job_request_state_machine BEFORE UPDATE ON job_requests FOR EACH ROW EXECUTE FUNCTION enforce_job_request_state_machine()"},{"name":"trg_job_requests_updated_at","definition":"CREATE TRIGGER trg_job_requests_updated_at BEFORE UPDATE ON job_requests FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"},{"name":"trg_notify_managers_on_new_job_request","definition":"CREATE TRIGGER trg_notify_managers_on_new_job_request AFTER INSERT ON job_requests FOR EACH ROW EXECUTE FUNCTION tg_notify_managers_on_new_job_request()"}],"constraints":[{"name":"job_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"job_requests_source_kind_check","definition":"CHECK (source_kind = ANY (ARRAY['manual'::text, 'signed_work_auth'::text, 'imported'::text, 'other'::text]))"},{"name":"job_requests_source_signed_agreement_id_key","definition":"UNIQUE (source_signed_agreement_id)"}]},{"table":"job_requests_activity_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"job_request_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_jral_request","definition":"CREATE INDEX idx_jral_request ON public.job_requests_activity_log USING btree (job_request_id)"},{"name":"job_requests_activity_log_pkey","definition":"CREATE UNIQUE INDEX job_requests_activity_log_pkey ON public.job_requests_activity_log USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"job_requests_activity_log","permissive":"PERMISSIVE","policyname":"jral_insert","schemaname":"public","with_check":"is_tenant_member(tenant_id, uid())"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_id, uid()) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"job_requests_activity_log","permissive":"PERMISSIVE","policyname":"jral_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"job_requests_activity_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_sheet","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"job_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'Scheduled'::text","identity":"","not_null":false,"generated":""},{"name":"scheduled_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_crew","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"job_sheet_job_id_key","definition":"CREATE UNIQUE INDEX job_sheet_job_id_key ON public.job_sheet USING btree (job_id)"},{"name":"job_sheet_pkey","definition":"CREATE UNIQUE INDEX job_sheet_pkey ON public.job_sheet USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = job_sheet.tenant_org_id))))","roles":["public"],"tablename":"job_sheet","permissive":"PERMISSIVE","policyname":"Users view tenant jobs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"job_sheet_job_id_key","definition":"UNIQUE (job_id)"},{"name":"job_sheet_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_time_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"clock_in_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"clock_out_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_minutes","type":"integer","default":"\nCASE\n    WHEN (clock_out_at IS NOT NULL) THEN ((EXTRACT(epoch FROM (clock_out_at - clock_in_at)))::integer / 60)\n    ELSE NULL::integer\nEND","identity":"","not_null":false,"generated":"s"},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"clock_in_location","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"clock_out_location","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_job_time_logs_job","definition":"CREATE INDEX idx_job_time_logs_job ON public.job_time_logs USING btree (job_id)"},{"name":"idx_job_time_logs_open","definition":"CREATE INDEX idx_job_time_logs_open ON public.job_time_logs USING btree (user_id, job_id) WHERE (clock_out_at IS NULL)"},{"name":"idx_job_time_logs_tenant","definition":"CREATE INDEX idx_job_time_logs_tenant ON public.job_time_logs USING btree (tenant_org_id)"},{"name":"idx_job_time_logs_user","definition":"CREATE INDEX idx_job_time_logs_user ON public.job_time_logs USING btree (user_id)"},{"name":"job_time_logs_pkey","definition":"CREATE UNIQUE INDEX job_time_logs_pkey ON public.job_time_logs USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_owner(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"job_time_logs","permissive":"PERMISSIVE","policyname":"Owners delete tenant time logs","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_owner(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"job_time_logs","permissive":"PERMISSIVE","policyname":"Owners update tenant time logs","schemaname":"public","with_check":"is_tenant_owner(uid(), tenant_org_id)"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"job_time_logs","permissive":"PERMISSIVE","policyname":"Users create own time logs","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"job_time_logs","permissive":"PERMISSIVE","policyname":"Users update own time logs","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"job_time_logs","permissive":"PERMISSIVE","policyname":"Users view own time logs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_org_id)))","roles":["public"],"tablename":"job_time_logs","permissive":"PERMISSIVE","policyname":"time_logs_tenant_owner_select","schemaname":"public","with_check":null}],"triggers":[{"name":"update_job_time_logs_updated_at","definition":"CREATE TRIGGER update_job_time_logs_updated_at BEFORE UPDATE ON job_time_logs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"job_time_logs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"job_verification_checklist","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"photos_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"aerial_uploaded","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"closeups_uploaded","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"notes_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"customer_signature","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"work_auth_signed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"invoice_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"docs_reviewed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"last_updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"job_verification_checklist_job_id_key","definition":"CREATE UNIQUE INDEX job_verification_checklist_job_id_key ON public.job_verification_checklist USING btree (job_id)"},{"name":"job_verification_checklist_pkey","definition":"CREATE UNIQUE INDEX job_verification_checklist_pkey ON public.job_verification_checklist USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(is_tenant_member(tenant_id, uid()) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"job_verification_checklist","permissive":"PERMISSIVE","policyname":"jvc_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(is_manager_or_higher_strict(uid(), tenant_id) OR has_acting_pm_grant(uid(), tenant_id) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"job_verification_checklist","permissive":"PERMISSIVE","policyname":"jvc_write","schemaname":"public","with_check":"(is_manager_or_higher_strict(uid(), tenant_id) OR has_acting_pm_grant(uid(), tenant_id) OR is_platform_admin(uid()))"}],"triggers":[{"name":"trg_jvc_updated_at","definition":"CREATE TRIGGER trg_jvc_updated_at BEFORE UPDATE ON job_verification_checklist FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"job_verification_checklist_job_id_key","definition":"UNIQUE (job_id)"},{"name":"job_verification_checklist_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"jobs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"appointment_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"latitude","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"longitude","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_type","type":"text","default":"'tarp'::text","identity":"","not_null":true,"generated":""},{"name":"priority","type":"text","default":"'normal'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'scheduled'::text","identity":"","not_null":true,"generated":""},{"name":"assigned_crew_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_crew_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_pm_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_pm_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scheduled_date","type":"date","default":"CURRENT_DATE","identity":"","not_null":true,"generated":""},{"name":"scheduled_time","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"appointment_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"work_auth_signed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"tarp_installed","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"photos_uploaded","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"docs_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"special_instructions","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"crew_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pm_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"manager_approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"manager_approved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_job_request_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_signed_agreement_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_status","type":"sce_claim_payment_status","default":"'not_started'::sce_claim_payment_status","identity":"","not_null":true,"generated":""},{"name":"tarping_invoice_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"invoice_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"submitted_to_carrier_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_sent_to_homeowner_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_status_v2","type":"claim_payment_lifecycle","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_payment_status_v2_updated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"funding_type","type":"text","default":"'retail'::text","identity":"","not_null":true,"generated":""},{"name":"financing_mode","type":"text","default":"'none'::text","identity":"","not_null":true,"generated":""},{"name":"financed_amount","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_jobs_assigned_crew","definition":"CREATE INDEX idx_jobs_assigned_crew ON public.jobs USING btree (assigned_crew_id)"},{"name":"idx_jobs_claim_payment_status","definition":"CREATE INDEX idx_jobs_claim_payment_status ON public.jobs USING btree (tenant_id, claim_payment_status)"},{"name":"idx_jobs_contact","definition":"CREATE INDEX idx_jobs_contact ON public.jobs USING btree (contact_id)"},{"name":"idx_jobs_contact_claim_id","definition":"CREATE INDEX idx_jobs_contact_claim_id ON public.jobs USING btree (contact_claim_id) WHERE (contact_claim_id IS NOT NULL)"},{"name":"idx_jobs_scheduled_date","definition":"CREATE INDEX idx_jobs_scheduled_date ON public.jobs USING btree (tenant_id, scheduled_date)"},{"name":"idx_jobs_source_job_request_id","definition":"CREATE INDEX idx_jobs_source_job_request_id ON public.jobs USING btree (source_job_request_id)"},{"name":"idx_jobs_source_signed_agreement_id","definition":"CREATE INDEX idx_jobs_source_signed_agreement_id ON public.jobs USING btree (source_signed_agreement_id)"},{"name":"idx_jobs_status","definition":"CREATE INDEX idx_jobs_status ON public.jobs USING btree (tenant_id, status)"},{"name":"idx_jobs_tenant","definition":"CREATE INDEX idx_jobs_tenant ON public.jobs USING btree (tenant_id)"},{"name":"jobs_pkey","definition":"CREATE UNIQUE INDEX jobs_pkey ON public.jobs USING btree (id)"},{"name":"jobs_tenant_id_job_number_key","definition":"CREATE UNIQUE INDEX jobs_tenant_id_job_number_key ON public.jobs USING btree (tenant_id, job_number)"}],"policies":[{"cmd":"DELETE","qual":"(is_system_admin(uid()) OR is_manager_or_higher(uid(), tenant_id))","roles":["authenticated"],"tablename":"jobs","permissive":"PERMISSIVE","policyname":"jobs_delete_manager_plus","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"jobs","permissive":"PERMISSIVE","policyname":"jobs_insert_manager_plus","schemaname":"public","with_check":"(is_system_admin(uid()) OR is_manager_or_higher(uid(), tenant_id))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"jobs","permissive":"PERMISSIVE","policyname":"jobs_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"true","roles":["service_role"],"tablename":"jobs","permissive":"PERMISSIVE","policyname":"jobs_service_role_all","schemaname":"public","with_check":"true"},{"cmd":"UPDATE","qual":"(assigned_crew_id = uid())","roles":["authenticated"],"tablename":"jobs","permissive":"PERMISSIVE","policyname":"jobs_update_assigned_crew","schemaname":"public","with_check":"(assigned_crew_id = uid())"},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR is_manager_or_higher(uid(), tenant_id))","roles":["authenticated"],"tablename":"jobs","permissive":"PERMISSIVE","policyname":"jobs_update_manager_plus","schemaname":"public","with_check":"(is_system_admin(uid()) OR is_manager_or_higher(uid(), tenant_id))"}],"triggers":[{"name":"bootstrap_roofing_project_ops","definition":"CREATE TRIGGER bootstrap_roofing_project_ops AFTER INSERT OR UPDATE OF contact_id, funding_type, financing_mode, status ON jobs FOR EACH ROW EXECUTE FUNCTION bootstrap_roofing_project_ops()"},{"name":"trg_enforce_job_verify_authority","definition":"CREATE TRIGGER trg_enforce_job_verify_authority BEFORE UPDATE ON jobs FOR EACH ROW EXECUTE FUNCTION enforce_job_verify_authority()"},{"name":"trg_enforce_jobs_crew_update_scope","definition":"CREATE TRIGGER trg_enforce_jobs_crew_update_scope BEFORE UPDATE ON jobs FOR EACH ROW EXECUTE FUNCTION enforce_jobs_crew_update_scope()"},{"name":"trg_jobs_contact_claim_link_check","definition":"CREATE TRIGGER trg_jobs_contact_claim_link_check BEFORE INSERT OR UPDATE OF contact_claim_id, contact_id, tenant_id ON jobs FOR EACH ROW EXECUTE FUNCTION jobs_contact_claim_link_check()"},{"name":"trg_jobs_set_job_number","definition":"CREATE TRIGGER trg_jobs_set_job_number BEFORE INSERT ON jobs FOR EACH ROW EXECUTE FUNCTION jobs_set_job_number()"},{"name":"trg_jobs_updated_at","definition":"CREATE TRIGGER trg_jobs_updated_at BEFORE UPDATE ON jobs FOR EACH ROW EXECUTE FUNCTION jobs_set_updated_at()"},{"name":"trg_jobs_verify_authority","definition":"CREATE TRIGGER trg_jobs_verify_authority BEFORE UPDATE ON jobs FOR EACH ROW EXECUTE FUNCTION enforce_job_verify_authority()"},{"name":"trg_jobs_verify_checklist","definition":"CREATE TRIGGER trg_jobs_verify_checklist BEFORE UPDATE ON jobs FOR EACH ROW EXECUTE FUNCTION enforce_job_verify_checklist()"}],"constraints":[{"name":"jobs_contact_id_unified_contacts_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"jobs_financed_amount_nonnegative_check","definition":"CHECK (financed_amount >= 0::numeric)"},{"name":"jobs_financing_mode_check","definition":"CHECK (financing_mode = ANY (ARRAY['none'::text, 'partial'::text, 'full'::text]))"},{"name":"jobs_funding_type_check","definition":"CHECK (funding_type = ANY (ARRAY['retail'::text, 'insurance'::text]))"},{"name":"jobs_pkey","definition":"PRIMARY KEY (id)"},{"name":"jobs_priority_check","definition":"CHECK (priority = ANY (ARRAY['low'::text, 'normal'::text, 'high'::text, 'urgent'::text]))"},{"name":"jobs_status_check","definition":"CHECK (status = ANY (ARRAY['signed_authorization_received'::text, 'job_request_pending'::text, 'job_request_approved'::text, 'scheduled'::text, 'acknowledged'::text, 'dispatched'::text, 'on_site'::text, 'in_progress'::text, 'crew_completed'::text, 'pm_verifying'::text, 'pm_verified'::text, 'manager_review'::text, 'manager_approved'::text, 'payroll_ready'::text, 'submitted'::text, 'completed'::text, 'verified'::text, 'paid'::text, 'cancelled'::text]))"},{"name":"jobs_tenant_id_job_number_key","definition":"UNIQUE (tenant_id, job_number)"}]},{"table":"jurisdiction_scraper_configs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"county_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"state_code","type":"text","default":"'FL'::text","identity":"","not_null":true,"generated":""},{"name":"appraiser_url","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"search_url_pattern","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"api_endpoint","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scraper_type","type":"text","default":"'html'::text","identity":"","not_null":true,"generated":""},{"name":"selectors","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"field_mappings","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"headers","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"discovered_by_ai","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"verified","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"last_verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_jurisdiction_scraper_configs_county","definition":"CREATE INDEX idx_jurisdiction_scraper_configs_county ON public.jurisdiction_scraper_configs USING btree (lower(county_name))"},{"name":"jurisdiction_scraper_configs_county_name_key","definition":"CREATE UNIQUE INDEX jurisdiction_scraper_configs_county_name_key ON public.jurisdiction_scraper_configs USING btree (county_name)"},{"name":"jurisdiction_scraper_configs_pkey","definition":"CREATE UNIQUE INDEX jurisdiction_scraper_configs_pkey ON public.jurisdiction_scraper_configs USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"jurisdiction_scraper_configs","permissive":"PERMISSIVE","policyname":"jurisdiction_scraper_configs_admin_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"jurisdiction_scraper_configs","permissive":"PERMISSIVE","policyname":"system_admins_manage_scraper_configs","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"jurisdiction_scraper_configs_county_name_key","definition":"UNIQUE (county_name)"},{"name":"jurisdiction_scraper_configs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"jurisdictions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"state_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"county_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parcel_source_strategy","type":"parcel_source_strategy","default":"'ParcelDB'::parcel_source_strategy","identity":"","not_null":true,"generated":""},{"name":"parcel_data_drive_folder_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip_codes","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_jurisdictions_code","definition":"CREATE INDEX idx_jurisdictions_code ON public.jurisdictions USING btree (code)"},{"name":"idx_jurisdictions_state_county","definition":"CREATE INDEX idx_jurisdictions_state_county ON public.jurisdictions USING btree (state_code, county_name)"},{"name":"idx_jurisdictions_zip_codes","definition":"CREATE INDEX idx_jurisdictions_zip_codes ON public.jurisdictions USING gin (zip_codes)"},{"name":"jurisdictions_code_key","definition":"CREATE UNIQUE INDEX jurisdictions_code_key ON public.jurisdictions USING btree (code)"},{"name":"jurisdictions_pkey","definition":"CREATE UNIQUE INDEX jurisdictions_pkey ON public.jurisdictions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"jurisdictions","permissive":"PERMISSIVE","policyname":"Users can view jurisdictions","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"jurisdictions","permissive":"PERMISSIVE","policyname":"platform_admin_manage_jurisdictions","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"update_jurisdictions_updated_at","definition":"CREATE TRIGGER update_jurisdictions_updated_at BEFORE UPDATE ON jurisdictions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"jurisdictions_code_key","definition":"UNIQUE (code)"},{"name":"jurisdictions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"knocklaunch_demo_request_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"request_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"knocklaunch_demo_request_events_pkey","definition":"CREATE UNIQUE INDEX knocklaunch_demo_request_events_pkey ON public.knocklaunch_demo_request_events USING btree (id)"},{"name":"knocklaunch_demo_request_events_request_created_idx","definition":"CREATE INDEX knocklaunch_demo_request_events_request_created_idx ON public.knocklaunch_demo_request_events USING btree (request_id, created_at DESC)"},{"name":"knocklaunch_demo_request_events_request_id_event_type_key","definition":"CREATE UNIQUE INDEX knocklaunch_demo_request_events_request_id_event_type_key ON public.knocklaunch_demo_request_events USING btree (request_id, event_type)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"knocklaunch_demo_request_events","permissive":"PERMISSIVE","policyname":"authenticated users can read demo request events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"knocklaunch_demo_request_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"knocklaunch_demo_request_events_request_id_event_type_key","definition":"UNIQUE (request_id, event_type)"},{"name":"knocklaunch_demo_request_events_request_id_fkey","definition":"FOREIGN KEY (request_id) REFERENCES knocklaunch_demo_requests(id) ON DELETE CASCADE"}]},{"table":"knocklaunch_demo_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'business_card_qr'::text","identity":"","not_null":true,"generated":""},{"name":"business_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"business_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"website_or_social","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_help","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"primary_pain_point","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_area","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"logo_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"has_logo","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"landing_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'received'::text","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"opportunity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"demo_brief","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"confirmation_email_status","type":"text","default":"'not_queued'::text","identity":"","not_null":true,"generated":""},{"name":"owner_alert_status","type":"text","default":"'not_queued'::text","identity":"","not_null":true,"generated":""},{"name":"enrichment_status","type":"text","default":"'not_requested'::text","identity":"","not_null":true,"generated":""},{"name":"enrichment_data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"workflow_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"processed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"knocklaunch_demo_requests_email_created_idx","definition":"CREATE INDEX knocklaunch_demo_requests_email_created_idx ON public.knocklaunch_demo_requests USING btree (lower(email), created_at DESC)"},{"name":"knocklaunch_demo_requests_opportunity_idx","definition":"CREATE INDEX knocklaunch_demo_requests_opportunity_idx ON public.knocklaunch_demo_requests USING btree (opportunity_id) WHERE (opportunity_id IS NOT NULL)"},{"name":"knocklaunch_demo_requests_pkey","definition":"CREATE UNIQUE INDEX knocklaunch_demo_requests_pkey ON public.knocklaunch_demo_requests USING btree (id)"},{"name":"knocklaunch_demo_requests_status_updated_idx","definition":"CREATE INDEX knocklaunch_demo_requests_status_updated_idx ON public.knocklaunch_demo_requests USING btree (status, updated_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"knocklaunch_demo_requests","permissive":"PERMISSIVE","policyname":"authenticated users can read demo requests","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"true","roles":["authenticated"],"tablename":"knocklaunch_demo_requests","permissive":"PERMISSIVE","policyname":"authenticated users can update demo requests","schemaname":"public","with_check":"true"}],"triggers":[],"constraints":[{"name":"knocklaunch_demo_requests_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"knocklaunch_demo_requests_opportunity_id_fkey","definition":"FOREIGN KEY (opportunity_id) REFERENCES business_opportunities(id) ON DELETE SET NULL"},{"name":"knocklaunch_demo_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"knocklaunch_demo_requests_status_check","definition":"CHECK (status = ANY (ARRAY['new'::text, 'received'::text, 'preparing'::text, 'ready_for_review'::text, 'workflow_failed'::text, 'reviewing'::text, 'demo_building'::text, 'demo_ready'::text, 'contacted'::text, 'closed'::text]))"}]},{"table":"kpi_goals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"kpi_name","type":"character varying(100)","default":null,"identity":"","not_null":true,"generated":""},{"name":"target_value","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"current_value","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"period_type","type":"character varying(20)","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_start","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_end","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"goal_type","type":"character varying(50)","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_kpi_goals_period","definition":"CREATE INDEX idx_kpi_goals_period ON public.kpi_goals USING btree (period_start, period_end)"},{"name":"idx_kpi_goals_tenant","definition":"CREATE INDEX idx_kpi_goals_tenant ON public.kpi_goals USING btree (tenant_id)"},{"name":"kpi_goals_pkey","definition":"CREATE UNIQUE INDEX kpi_goals_pkey ON public.kpi_goals USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"kpi_goals","permissive":"PERMISSIVE","policyname":"Users can manage KPIs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"kpi_goals","permissive":"PERMISSIVE","policyname":"Users can view own tenant KPIs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"kpi_goals_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lawn_care_readiness_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"item_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"item_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"role_or_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"serial","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_lawn_care_readiness_tenant_type","definition":"CREATE INDEX idx_lawn_care_readiness_tenant_type ON public.lawn_care_readiness_items USING btree (tenant_id, item_type)"},{"name":"lawn_care_readiness_items_pkey","definition":"CREATE UNIQUE INDEX lawn_care_readiness_items_pkey ON public.lawn_care_readiness_items USING btree (id)"},{"name":"lawn_care_readiness_items_tenant_id_item_type_item_id_key","definition":"CREATE UNIQUE INDEX lawn_care_readiness_items_tenant_id_item_type_item_id_key ON public.lawn_care_readiness_items USING btree (tenant_id, item_type, item_id)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_care_readiness_items","permissive":"PERMISSIVE","policyname":"lawn_readiness_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lawn_care_readiness_items","permissive":"PERMISSIVE","policyname":"lawn_readiness_insert","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_care_readiness_items","permissive":"PERMISSIVE","policyname":"lawn_readiness_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_care_readiness_items","permissive":"PERMISSIVE","policyname":"lawn_readiness_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_lawn_care_readiness_items_updated_at","definition":"CREATE TRIGGER trg_lawn_care_readiness_items_updated_at BEFORE UPDATE ON lawn_care_readiness_items FOR EACH ROW EXECUTE FUNCTION touch_lawn_care_readiness_items_updated_at()"}],"constraints":[{"name":"lawn_care_readiness_items_item_type_check","definition":"CHECK (item_type = ANY (ARRAY['gear'::text, 'crew'::text]))"},{"name":"lawn_care_readiness_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"lawn_care_readiness_items_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"lawn_care_readiness_items_tenant_id_item_type_item_id_key","definition":"UNIQUE (tenant_id, item_type, item_id)"}]},{"table":"lawn_service_plans","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"cadence","type":"text","default":"'biweekly'::text","identity":"","not_null":true,"generated":""},{"name":"route_day","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_price","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"turf_sq_ft","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"edging_linear_ft","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"beds_sq_ft","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"shrub_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"access_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pause_until","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_crew_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_service_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_service_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_lawn_service_plans_tenant_day","definition":"CREATE INDEX idx_lawn_service_plans_tenant_day ON public.lawn_service_plans USING btree (tenant_id, route_day, status)"},{"name":"lawn_service_plans_pkey","definition":"CREATE UNIQUE INDEX lawn_service_plans_pkey ON public.lawn_service_plans USING btree (id)"},{"name":"lawn_service_plans_tenant_id_contact_id_key","definition":"CREATE UNIQUE INDEX lawn_service_plans_tenant_id_contact_id_key ON public.lawn_service_plans USING btree (tenant_id, contact_id)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_plans","permissive":"PERMISSIVE","policyname":"lawn_service_plans_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lawn_service_plans","permissive":"PERMISSIVE","policyname":"lawn_service_plans_insert","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_plans","permissive":"PERMISSIVE","policyname":"lawn_service_plans_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_plans","permissive":"PERMISSIVE","policyname":"lawn_service_plans_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_lawn_service_plans_updated_at","definition":"CREATE TRIGGER trg_lawn_service_plans_updated_at BEFORE UPDATE ON lawn_service_plans FOR EACH ROW EXECUTE FUNCTION touch_lawn_service_updated_at()"}],"constraints":[{"name":"lawn_service_plans_cadence_check","definition":"CHECK (cadence = ANY (ARRAY['weekly'::text, 'biweekly'::text, 'monthly'::text, 'one_time'::text]))"},{"name":"lawn_service_plans_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE CASCADE"},{"name":"lawn_service_plans_pkey","definition":"PRIMARY KEY (id)"},{"name":"lawn_service_plans_status_check","definition":"CHECK (status = ANY (ARRAY['lead'::text, 'active'::text, 'paused'::text, 'cancelled'::text]))"},{"name":"lawn_service_plans_tenant_id_contact_id_key","definition":"UNIQUE (tenant_id, contact_id)"},{"name":"lawn_service_plans_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"lawn_service_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"request_action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'received'::text","identity":"","not_null":true,"generated":""},{"name":"service_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_price","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_cadence","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"preferred_day","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pause_option","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resume_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_lawn_service_requests_tenant_status","definition":"CREATE INDEX idx_lawn_service_requests_tenant_status ON public.lawn_service_requests USING btree (tenant_id, status, created_at DESC)"},{"name":"lawn_service_requests_pkey","definition":"CREATE UNIQUE INDEX lawn_service_requests_pkey ON public.lawn_service_requests USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_requests","permissive":"PERMISSIVE","policyname":"lawn_service_requests_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lawn_service_requests","permissive":"PERMISSIVE","policyname":"lawn_service_requests_insert","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_requests","permissive":"PERMISSIVE","policyname":"lawn_service_requests_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_requests","permissive":"PERMISSIVE","policyname":"lawn_service_requests_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_lawn_service_requests_updated_at","definition":"CREATE TRIGGER trg_lawn_service_requests_updated_at BEFORE UPDATE ON lawn_service_requests FOR EACH ROW EXECUTE FUNCTION touch_lawn_service_updated_at()"}],"constraints":[{"name":"lawn_service_requests_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"lawn_service_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"lawn_service_requests_status_check","definition":"CHECK (status = ANY (ARRAY['received'::text, 'reviewing'::text, 'estimated'::text, 'accepted'::text, 'scheduled'::text, 'completed'::text, 'declined'::text, 'cancelled'::text]))"},{"name":"lawn_service_requests_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"lawn_service_routes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"service_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'planned'::text","identity":"","not_null":true,"generated":""},{"name":"assigned_crew_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"exception_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"exception_note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"lawn_service_routes_pkey","definition":"CREATE UNIQUE INDEX lawn_service_routes_pkey ON public.lawn_service_routes USING btree (id)"},{"name":"lawn_service_routes_tenant_id_service_date_key","definition":"CREATE UNIQUE INDEX lawn_service_routes_tenant_id_service_date_key ON public.lawn_service_routes USING btree (tenant_id, service_date)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_routes","permissive":"PERMISSIVE","policyname":"lawn_service_routes_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lawn_service_routes","permissive":"PERMISSIVE","policyname":"lawn_service_routes_insert","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_routes","permissive":"PERMISSIVE","policyname":"lawn_service_routes_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_routes","permissive":"PERMISSIVE","policyname":"lawn_service_routes_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_lawn_service_routes_updated_at","definition":"CREATE TRIGGER trg_lawn_service_routes_updated_at BEFORE UPDATE ON lawn_service_routes FOR EACH ROW EXECUTE FUNCTION touch_lawn_service_updated_at()"}],"constraints":[{"name":"lawn_service_routes_pkey","definition":"PRIMARY KEY (id)"},{"name":"lawn_service_routes_status_check","definition":"CHECK (status = ANY (ARRAY['planned'::text, 'dispatched'::text, 'in_progress'::text, 'complete'::text, 'cancelled'::text]))"},{"name":"lawn_service_routes_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"lawn_service_routes_tenant_id_service_date_key","definition":"UNIQUE (tenant_id, service_date)"}]},{"table":"lawn_service_visits","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"route_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_plan_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"service_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"stop_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'scheduled'::text","identity":"","not_null":true,"generated":""},{"name":"assigned_crew_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"checklist","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"evidence","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"exception_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"exception_note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"invoice_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_lawn_service_visits_tenant_date","definition":"CREATE INDEX idx_lawn_service_visits_tenant_date ON public.lawn_service_visits USING btree (tenant_id, service_date, stop_order)"},{"name":"lawn_service_visits_pkey","definition":"CREATE UNIQUE INDEX lawn_service_visits_pkey ON public.lawn_service_visits USING btree (id)"},{"name":"lawn_service_visits_tenant_id_contact_id_service_date_key","definition":"CREATE UNIQUE INDEX lawn_service_visits_tenant_id_contact_id_service_date_key ON public.lawn_service_visits USING btree (tenant_id, contact_id, service_date)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_visits","permissive":"PERMISSIVE","policyname":"lawn_service_visits_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lawn_service_visits","permissive":"PERMISSIVE","policyname":"lawn_service_visits_insert","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_visits","permissive":"PERMISSIVE","policyname":"lawn_service_visits_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"lawn_service_visits","permissive":"PERMISSIVE","policyname":"lawn_service_visits_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_lawn_service_visits_updated_at","definition":"CREATE TRIGGER trg_lawn_service_visits_updated_at BEFORE UPDATE ON lawn_service_visits FOR EACH ROW EXECUTE FUNCTION touch_lawn_service_updated_at()"}],"constraints":[{"name":"lawn_service_visits_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE CASCADE"},{"name":"lawn_service_visits_pkey","definition":"PRIMARY KEY (id)"},{"name":"lawn_service_visits_route_id_fkey","definition":"FOREIGN KEY (route_id) REFERENCES lawn_service_routes(id) ON DELETE SET NULL"},{"name":"lawn_service_visits_service_plan_id_fkey","definition":"FOREIGN KEY (service_plan_id) REFERENCES lawn_service_plans(id) ON DELETE SET NULL"},{"name":"lawn_service_visits_status_check","definition":"CHECK (status = ANY (ARRAY['scheduled'::text, 'in_progress'::text, 'complete'::text, 'skipped'::text, 'rescheduled'::text, 'blocked'::text, 'cancelled'::text]))"},{"name":"lawn_service_visits_tenant_id_contact_id_service_date_key","definition":"UNIQUE (tenant_id, contact_id, service_date)"},{"name":"lawn_service_visits_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"lead_batch_rows","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"batch_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"row_index","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"normalized_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"tags","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"match_decision","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"matched_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"compliance_results","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"mapping_metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_batch_rows_batch","definition":"CREATE INDEX idx_lead_batch_rows_batch ON public.lead_batch_rows USING btree (batch_id)"},{"name":"idx_lead_batch_rows_decision","definition":"CREATE INDEX idx_lead_batch_rows_decision ON public.lead_batch_rows USING btree (batch_id, match_decision)"},{"name":"lead_batch_rows_pkey","definition":"CREATE UNIQUE INDEX lead_batch_rows_pkey ON public.lead_batch_rows USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM (lead_batches lb\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = lb.tenant_org_id)))\n  WHERE ((lb.id = lead_batch_rows.batch_id) AND (utm.user_id = uid()))))","roles":["public"],"tablename":"lead_batch_rows","permissive":"PERMISSIVE","policyname":"Users view tenant batch rows","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lead_batch_rows","permissive":"PERMISSIVE","policyname":"users_insert_tenant_batch_rows","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (lead_batches lb\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = lb.tenant_org_id)))\n  WHERE ((lb.id = lead_batch_rows.batch_id) AND (utm.user_id = uid()) AND (utm.status = 'active'::text)))))"},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (lead_batches lb\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = lb.tenant_org_id)))\n  WHERE ((lb.id = lead_batch_rows.batch_id) AND (utm.user_id = uid()) AND (utm.status = 'active'::text)))))","roles":["authenticated"],"tablename":"lead_batch_rows","permissive":"PERMISSIVE","policyname":"users_update_tenant_batch_rows","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (lead_batches lb\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = lb.tenant_org_id)))\n  WHERE ((lb.id = lead_batch_rows.batch_id) AND (utm.user_id = uid()) AND (utm.status = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"lead_batch_rows_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_batches","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"mapped_columns","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"total_rows","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"processed_rows","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"success_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"update_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"error_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"import_kind","type":"text","default":"'csv'::text","identity":"","not_null":true,"generated":""},{"name":"dedup_summary","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"compliance_summary","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_batches_import_kind","definition":"CREATE INDEX idx_lead_batches_import_kind ON public.lead_batches USING btree (import_kind)"},{"name":"idx_lead_batches_status","definition":"CREATE INDEX idx_lead_batches_status ON public.lead_batches USING btree (status)"},{"name":"idx_lead_batches_tenant","definition":"CREATE INDEX idx_lead_batches_tenant ON public.lead_batches USING btree (tenant_org_id)"},{"name":"lead_batches_pkey","definition":"CREATE UNIQUE INDEX lead_batches_pkey ON public.lead_batches USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"lead_batches","permissive":"PERMISSIVE","policyname":"Users create tenant batches","schemaname":"public","with_check":"((created_by = uid()) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = lead_batches.tenant_org_id)))))"},{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = lead_batches.tenant_org_id))))","roles":["public"],"tablename":"lead_batches","permissive":"PERMISSIVE","policyname":"Users update tenant batches","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = lead_batches.tenant_org_id))))","roles":["public"],"tablename":"lead_batches","permissive":"PERMISSIVE","policyname":"Users view tenant batches","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_batches_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"start_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"end_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_zips","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_lead_campaigns_tenant","definition":"CREATE INDEX idx_lead_campaigns_tenant ON public.lead_campaigns USING btree (tenant_org_id, is_active)"},{"name":"lead_campaigns_pkey","definition":"CREATE UNIQUE INDEX lead_campaigns_pkey ON public.lead_campaigns USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"lead_campaigns","permissive":"PERMISSIVE","policyname":"campaigns_delete_tenant_or_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lead_campaigns","permissive":"PERMISSIVE","policyname":"campaigns_insert_tenant_or_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_tenant_member(tenant_org_id) OR is_system_admin(uid())))"},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND (uid() IS NOT NULL))","roles":["authenticated"],"tablename":"lead_campaigns","permissive":"RESTRICTIVE","policyname":"campaigns_restrict_null_or_anon","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (uid() IS NOT NULL))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"lead_campaigns","permissive":"PERMISSIVE","policyname":"campaigns_select_tenant_or_admin","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"lead_campaigns","permissive":"PERMISSIVE","policyname":"campaigns_update_tenant_or_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_tenant_member(tenant_org_id) OR is_system_admin(uid())))"}],"triggers":[{"name":"trg_lead_campaigns_updated_at","definition":"CREATE TRIGGER trg_lead_campaigns_updated_at BEFORE UPDATE ON lead_campaigns FOR EACH ROW EXECUTE FUNCTION touch_lead_campaigns_updated_at()"}],"constraints":[{"name":"lead_campaigns_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_deck","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'New'::text","identity":"","not_null":false,"generated":""},{"name":"priority","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"deletion_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"property_square_feet","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_parcel_id","type":"character varying(100)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data_fetched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_owner_name","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_assessed_value","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_bedrooms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_bathrooms","type":"numeric(3,1)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_year_built","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_lot_size","type":"numeric(10,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data_jurisdiction","type":"character varying(100)","default":null,"identity":"","not_null":false,"generated":""},{"name":"quality_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_stage","type":"text","default":"'New / Unassigned'::text","identity":"","not_null":false,"generated":""},{"name":"graduated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"geocoded_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"geocode_confidence","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"lost_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"referral_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referral_partner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_dnc","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"dnc_checked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_deck_assigned_to","definition":"CREATE INDEX idx_lead_deck_assigned_to ON public.lead_deck USING btree (assigned_to) WHERE (deleted_at IS NULL)"},{"name":"idx_lead_deck_campaign","definition":"CREATE INDEX idx_lead_deck_campaign ON public.lead_deck USING btree (campaign_id) WHERE (campaign_id IS NOT NULL)"},{"name":"idx_lead_deck_created_at","definition":"CREATE INDEX idx_lead_deck_created_at ON public.lead_deck USING btree (created_at DESC) WHERE (deleted_at IS NULL)"},{"name":"idx_lead_deck_deleted_at","definition":"CREATE INDEX idx_lead_deck_deleted_at ON public.lead_deck USING btree (deleted_at) WHERE (deleted_at IS NOT NULL)"},{"name":"idx_lead_deck_global_pool","definition":"CREATE INDEX idx_lead_deck_global_pool ON public.lead_deck USING btree (tenant_org_id, assigned_to, status) WHERE (tenant_org_id IS NULL)"},{"name":"idx_lead_deck_is_dnc","definition":"CREATE INDEX idx_lead_deck_is_dnc ON public.lead_deck USING btree (is_dnc) WHERE (is_dnc = false)"},{"name":"idx_lead_deck_lead_stage","definition":"CREATE INDEX idx_lead_deck_lead_stage ON public.lead_deck USING btree (lead_stage) WHERE (deleted_at IS NULL)"},{"name":"idx_lead_deck_priority","definition":"CREATE INDEX idx_lead_deck_priority ON public.lead_deck USING btree (tenant_org_id, created_at) WHERE ((phone IS NOT NULL) AND (email IS NOT NULL))"},{"name":"idx_lead_deck_property_fetched","definition":"CREATE INDEX idx_lead_deck_property_fetched ON public.lead_deck USING btree (property_data_fetched_at)"},{"name":"idx_lead_deck_property_parcel","definition":"CREATE INDEX idx_lead_deck_property_parcel ON public.lead_deck USING btree (property_parcel_id)"},{"name":"idx_lead_deck_status","definition":"CREATE INDEX idx_lead_deck_status ON public.lead_deck USING btree (status)"},{"name":"idx_lead_deck_tenant","definition":"CREATE INDEX idx_lead_deck_tenant ON public.lead_deck USING btree (tenant_org_id)"},{"name":"idx_lead_deck_tenant_assigned","definition":"CREATE INDEX idx_lead_deck_tenant_assigned ON public.lead_deck USING btree (tenant_org_id, assigned_to) WHERE (deleted_at IS NULL)"},{"name":"idx_lead_deck_tenant_org","definition":"CREATE INDEX idx_lead_deck_tenant_org ON public.lead_deck USING btree (tenant_org_id) WHERE (deleted_at IS NULL)"},{"name":"idx_lead_deck_tenant_org_id","definition":"CREATE INDEX idx_lead_deck_tenant_org_id ON public.lead_deck USING btree (tenant_org_id)"},{"name":"idx_lead_deck_tenant_status","definition":"CREATE INDEX idx_lead_deck_tenant_status ON public.lead_deck USING btree (tenant_org_id, status)"},{"name":"lead_deck_lead_id_key","definition":"CREATE UNIQUE INDEX lead_deck_lead_id_key ON public.lead_deck USING btree (lead_id)"},{"name":"lead_deck_pkey","definition":"CREATE UNIQUE INDEX lead_deck_pkey ON public.lead_deck USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_admin_all_select","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_for(uid(), tenant_org_id))","roles":["authenticated"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_owner_tenant_select","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_update","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(((tenant_org_id IS NULL) AND ((assigned_to IS NULL) OR (assigned_to = ''::text))) OR is_assigned_to(uid(), assigned_to))","roles":["authenticated"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"ld_user_pool_and_assigned_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"lead_deck","permissive":"PERMISSIVE","policyname":"tenant_members_all_leads","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"}],"triggers":[{"name":"lead_deck_auto_graduate","definition":"CREATE TRIGGER lead_deck_auto_graduate BEFORE UPDATE ON lead_deck FOR EACH ROW EXECUTE FUNCTION auto_graduate_lead()"},{"name":"lead_deck_quality_score","definition":"CREATE TRIGGER lead_deck_quality_score BEFORE INSERT OR UPDATE ON lead_deck FOR EACH ROW EXECUTE FUNCTION update_quality_score()"},{"name":"trg_audit_lead_deck_write","definition":"CREATE TRIGGER trg_audit_lead_deck_write AFTER INSERT OR DELETE OR UPDATE ON lead_deck FOR EACH ROW EXECUTE FUNCTION audit_lead_deck_write()"},{"name":"trg_mirror_lead_deck_to_unified","definition":"CREATE TRIGGER trg_mirror_lead_deck_to_unified AFTER INSERT OR DELETE OR UPDATE ON lead_deck FOR EACH ROW EXECUTE FUNCTION mirror_lead_deck_to_unified()"},{"name":"trg_scrub_lead_deck_dnc","definition":"CREATE TRIGGER trg_scrub_lead_deck_dnc BEFORE INSERT OR UPDATE OF phone ON lead_deck FOR EACH ROW EXECUTE FUNCTION scrub_lead_against_dnc()"},{"name":"trg_validate_assigned_to_ld","definition":"CREATE TRIGGER trg_validate_assigned_to_ld BEFORE INSERT OR UPDATE OF assigned_to ON lead_deck FOR EACH ROW EXECUTE FUNCTION validate_assigned_to_uuid()"},{"name":"update_lead_deck_updated_at","definition":"CREATE TRIGGER update_lead_deck_updated_at BEFORE UPDATE ON lead_deck FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"lead_deck_lead_id_key","definition":"UNIQUE (lead_id)"},{"name":"lead_deck_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_deck_write_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"op","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_deck_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"db_user","type":"text","default":"CURRENT_USER","identity":"","not_null":true,"generated":""},{"name":"auth_uid","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_hint","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_columns","type":"text[]","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_deck_write_audit_occurred_at","definition":"CREATE INDEX idx_lead_deck_write_audit_occurred_at ON public.lead_deck_write_audit USING btree (occurred_at DESC)"},{"name":"idx_lead_deck_write_audit_op","definition":"CREATE INDEX idx_lead_deck_write_audit_op ON public.lead_deck_write_audit USING btree (op)"},{"name":"lead_deck_write_audit_pkey","definition":"CREATE UNIQUE INDEX lead_deck_write_audit_pkey ON public.lead_deck_write_audit USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"lead_deck_write_audit","permissive":"PERMISSIVE","policyname":"System admins can read lead_deck write audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_deck_write_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_intelligence_scores","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"score_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"score","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"bucket","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"confidence","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rank","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"reasons","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"factors","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"recommended_action","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_script","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"dismissed_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"manually_boosted","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"manual_priority_override","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_priority_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_priority_set_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_priority_set_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"stale","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"stale_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_calculated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"model_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_lis_bucket","definition":"CREATE INDEX idx_lis_bucket ON public.lead_intelligence_scores USING btree (tenant_org_id, score_type, bucket)"},{"name":"idx_lis_stale","definition":"CREATE INDEX idx_lis_stale ON public.lead_intelligence_scores USING btree (tenant_org_id, score_type) WHERE (stale = true)"},{"name":"idx_lis_subject","definition":"CREATE INDEX idx_lis_subject ON public.lead_intelligence_scores USING btree (subject_type, subject_id)"},{"name":"idx_lis_tenant_score_rank","definition":"CREATE INDEX idx_lis_tenant_score_rank ON public.lead_intelligence_scores USING btree (tenant_org_id, score_type, score DESC) WHERE (dismissed = false)"},{"name":"lead_intelligence_scores_pkey","definition":"CREATE UNIQUE INDEX lead_intelligence_scores_pkey ON public.lead_intelligence_scores USING btree (id)"},{"name":"lis_unique_per_subject","definition":"CREATE UNIQUE INDEX lis_unique_per_subject ON public.lead_intelligence_scores USING btree (tenant_org_id, score_type, subject_type, subject_id)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"lead_intelligence_scores","permissive":"PERMISSIVE","policyname":"lis_admin_delete","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR is_admin_or_higher(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"lead_intelligence_scores","permissive":"PERMISSIVE","policyname":"lis_admin_update","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"lead_intelligence_scores","permissive":"PERMISSIVE","policyname":"lis_admin_write","schemaname":"public","with_check":"(is_system_admin(uid()) OR is_admin_or_higher(uid(), (tenant_org_id)::uuid))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"lead_intelligence_scores","permissive":"PERMISSIVE","policyname":"lis_select_tenant_member","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_lis_updated_at","definition":"CREATE TRIGGER trg_lis_updated_at BEFORE UPDATE ON lead_intelligence_scores FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"},{"name":"trg_sync_lead_score_to_contact","definition":"CREATE TRIGGER trg_sync_lead_score_to_contact AFTER INSERT OR UPDATE OF score ON lead_intelligence_scores FOR EACH ROW EXECUTE FUNCTION sync_lead_score_to_contact()"}],"constraints":[{"name":"lead_intelligence_scores_manual_priority_override_check","definition":"CHECK (manual_priority_override IS NULL OR manual_priority_override >= 0 AND manual_priority_override <= 100)"},{"name":"lead_intelligence_scores_pkey","definition":"PRIMARY KEY (id)"},{"name":"lead_intelligence_scores_score_check","definition":"CHECK (score >= 0 AND score <= 100)"},{"name":"lis_unique_per_subject","definition":"UNIQUE (tenant_org_id, score_type, subject_type, subject_id)"}]},{"table":"lead_lane_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_state","type":"lead_lane_state","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_state","type":"lead_lane_state","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"disclosure_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"lead_lane_audit_lead_idx","definition":"CREATE INDEX lead_lane_audit_lead_idx ON public.lead_lane_audit USING btree (tenant_org_id, lead_id, created_at DESC)"},{"name":"lead_lane_audit_pkey","definition":"CREATE UNIQUE INDEX lead_lane_audit_pkey ON public.lead_lane_audit USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"false","roles":["authenticated"],"tablename":"lead_lane_audit","permissive":"PERMISSIVE","policyname":"lane_audit_no_delete","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"false","roles":["authenticated"],"tablename":"lead_lane_audit","permissive":"PERMISSIVE","policyname":"lane_audit_no_update","schemaname":"public","with_check":"false"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lead_lane_audit","permissive":"PERMISSIVE","policyname":"lane_audit_tenant_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) AND (actor_user_id = uid()))"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"lead_lane_audit","permissive":"PERMISSIVE","policyname":"lane_audit_tenant_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_lane_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_lifecycle_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rule_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rule_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"conditions","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"enabled","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"lead_lifecycle_rules_pkey","definition":"CREATE UNIQUE INDEX lead_lifecycle_rules_pkey ON public.lead_lifecycle_rules USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((enabled = true) AND ((tenant_id IS NULL) OR (tenant_id IN ( SELECT utm.tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"lead_lifecycle_rules","permissive":"PERMISSIVE","policyname":"Tenant members view their lifecycle rules + globals","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"lead_lifecycle_rules","permissive":"PERMISSIVE","policyname":"platform_admin_manage_lifecycle_rules","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"lead_lifecycle_rules_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_lifecycle_stages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"color","type":"text","default":"'#6366f1'::text","identity":"","not_null":false,"generated":""},{"name":"icon","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"stage_order","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"is_system","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"auto_actions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"exit_criteria","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"entry_criteria","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"sla_hours","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_lifecycle_stages_tenant","definition":"CREATE INDEX idx_lead_lifecycle_stages_tenant ON public.lead_lifecycle_stages USING btree (tenant_org_id)"},{"name":"lead_lifecycle_stages_pkey","definition":"CREATE UNIQUE INDEX lead_lifecycle_stages_pkey ON public.lead_lifecycle_stages USING btree (id)"},{"name":"lead_lifecycle_stages_tenant_org_id_name_key","definition":"CREATE UNIQUE INDEX lead_lifecycle_stages_tenant_org_id_name_key ON public.lead_lifecycle_stages USING btree (tenant_org_id, name)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"lead_lifecycle_stages","permissive":"PERMISSIVE","policyname":"Tenant isolation for lead_lifecycle_stages","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_lifecycle_stages_pkey","definition":"PRIMARY KEY (id)"},{"name":"lead_lifecycle_stages_tenant_org_id_name_key","definition":"UNIQUE (tenant_org_id, name)"}]},{"table":"lead_repair_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"action_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_ids","type":"text[]","default":null,"identity":"","not_null":true,"generated":""},{"name":"performed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"details","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lra_created_at","definition":"CREATE INDEX idx_lra_created_at ON public.lead_repair_audit USING btree (created_at)"},{"name":"idx_lra_performed_by","definition":"CREATE INDEX idx_lra_performed_by ON public.lead_repair_audit USING btree (performed_by)"},{"name":"lead_repair_audit_pkey","definition":"CREATE UNIQUE INDEX lead_repair_audit_pkey ON public.lead_repair_audit USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(performed_by = uid())","roles":["authenticated"],"tablename":"lead_repair_audit","permissive":"PERMISSIVE","policyname":"Users can view their repair audits","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"lead_repair_audit","permissive":"PERMISSIVE","policyname":"authenticated_insert_repair_audit","schemaname":"public","with_check":"(uid() IS NOT NULL)"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"lead_repair_audit","permissive":"PERMISSIVE","policyname":"platform_admin_view_repair_audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_repair_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"lead_score_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"previous_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_score","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"score_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"change_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"factors","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_score_history_contact","definition":"CREATE INDEX idx_lead_score_history_contact ON public.lead_score_history USING btree (contact_id)"},{"name":"lead_score_history_pkey","definition":"CREATE UNIQUE INDEX lead_score_history_pkey ON public.lead_score_history USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"lead_score_history","permissive":"PERMISSIVE","policyname":"Tenant isolation for lead_score_history","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_score_history_pkey","definition":"PRIMARY KEY (id)"},{"name":"lead_score_history_score_type_check","definition":"CHECK (score_type = ANY (ARRAY['total'::text, 'data_quality'::text, 'engagement'::text, 'recency'::text, 'custom'::text]))"}]},{"table":"lead_stage_transitions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_stage_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_stage_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"transition_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"triggered_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"automation_rule_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"time_in_previous_stage_hours","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_lead_stage_transitions_contact","definition":"CREATE INDEX idx_lead_stage_transitions_contact ON public.lead_stage_transitions USING btree (contact_id)"},{"name":"lead_stage_transitions_pkey","definition":"CREATE UNIQUE INDEX lead_stage_transitions_pkey ON public.lead_stage_transitions USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"lead_stage_transitions","permissive":"PERMISSIVE","policyname":"Tenant isolation for lead_stage_transitions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"lead_stage_transitions_pkey","definition":"PRIMARY KEY (id)"},{"name":"lead_stage_transitions_triggered_by_check","definition":"CHECK (triggered_by = ANY (ARRAY['user'::text, 'automation'::text, 'system'::text]))"}]},{"table":"leads","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_damage_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"qualification_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"qualification_reasoning","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority_level","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_actions","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"qualified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_leads_created_at","definition":"CREATE INDEX idx_leads_created_at ON public.leads USING btree (created_at DESC)"},{"name":"idx_leads_priority","definition":"CREATE INDEX idx_leads_priority ON public.leads USING btree (priority_level) WHERE (priority_level IS NOT NULL)"},{"name":"leads_pkey","definition":"CREATE UNIQUE INDEX leads_pkey ON public.leads USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"leads","permissive":"PERMISSIVE","policyname":"Public can submit leads with valid name","schemaname":"public","with_check":"((name IS NOT NULL) AND (length(TRIM(BOTH FROM name)) > 0))"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"leads","permissive":"PERMISSIVE","policyname":"System admins can view submitted leads","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"leads_pkey","definition":"PRIMARY KEY (id)"},{"name":"leads_priority_level_check","definition":"CHECK (priority_level = ANY (ARRAY['high'::text, 'medium'::text, 'low'::text]))"},{"name":"leads_qualification_score_check","definition":"CHECK (qualification_score >= 0 AND qualification_score <= 100)"}]},{"table":"legal_page_versions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"legal_page_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body_format","type":"text","default":"'markdown'::text","identity":"","not_null":true,"generated":""},{"name":"effective_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"version","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"change_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_legal_page_versions_page","definition":"CREATE INDEX idx_legal_page_versions_page ON public.legal_page_versions USING btree (legal_page_id, version DESC)"},{"name":"idx_legal_page_versions_slug","definition":"CREATE INDEX idx_legal_page_versions_slug ON public.legal_page_versions USING btree (slug, version DESC)"},{"name":"legal_page_versions_pkey","definition":"CREATE UNIQUE INDEX legal_page_versions_pkey ON public.legal_page_versions USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"legal_page_versions","permissive":"PERMISSIVE","policyname":"System admins can insert legal page versions","schemaname":"public","with_check":"is_system_admin()"},{"cmd":"SELECT","qual":"is_system_admin()","roles":["authenticated"],"tablename":"legal_page_versions","permissive":"PERMISSIVE","policyname":"System admins can read legal page versions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"legal_page_versions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"legal_pages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body_format","type":"text","default":"'markdown'::text","identity":"","not_null":true,"generated":""},{"name":"effective_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"published_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"published_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_legal_pages_slug_status","definition":"CREATE INDEX idx_legal_pages_slug_status ON public.legal_pages USING btree (slug, status)"},{"name":"legal_pages_pkey","definition":"CREATE UNIQUE INDEX legal_pages_pkey ON public.legal_pages USING btree (id)"},{"name":"legal_pages_slug_key","definition":"CREATE UNIQUE INDEX legal_pages_slug_key ON public.legal_pages USING btree (slug)"}],"policies":[{"cmd":"SELECT","qual":"(status = 'published'::text)","roles":["anon","authenticated"],"tablename":"legal_pages","permissive":"PERMISSIVE","policyname":"Public can read published legal pages","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"legal_pages","permissive":"PERMISSIVE","policyname":"System admins can insert legal pages","schemaname":"public","with_check":"is_system_admin()"},{"cmd":"SELECT","qual":"is_system_admin()","roles":["authenticated"],"tablename":"legal_pages","permissive":"PERMISSIVE","policyname":"System admins can read all legal pages","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_system_admin()","roles":["authenticated"],"tablename":"legal_pages","permissive":"PERMISSIVE","policyname":"System admins can update legal pages","schemaname":"public","with_check":"is_system_admin()"}],"triggers":[{"name":"trg_legal_pages_updated_at","definition":"CREATE TRIGGER trg_legal_pages_updated_at BEFORE UPDATE ON legal_pages FOR EACH ROW EXECUTE FUNCTION tg_legal_pages_set_updated_at()"}],"constraints":[{"name":"legal_pages_body_format_check","definition":"CHECK (body_format = ANY (ARRAY['markdown'::text, 'html'::text, 'text'::text]))"},{"name":"legal_pages_pkey","definition":"PRIMARY KEY (id)"},{"name":"legal_pages_slug_key","definition":"UNIQUE (slug)"},{"name":"legal_pages_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'published'::text, 'archived'::text]))"}]},{"table":"litigator_suppression_list","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scope","type":"text","default":"'global'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"risk_level","type":"text","default":"'high'::text","identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"added_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"added_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_litigator_phone","definition":"CREATE INDEX idx_litigator_phone ON public.litigator_suppression_list USING btree (phone_normalized)"},{"name":"idx_litigator_tenant","definition":"CREATE INDEX idx_litigator_tenant ON public.litigator_suppression_list USING btree (tenant_org_id) WHERE (scope = 'tenant'::text)"},{"name":"litigator_suppression_list_pkey","definition":"CREATE UNIQUE INDEX litigator_suppression_list_pkey ON public.litigator_suppression_list USING btree (id)"},{"name":"uq_litigator_global","definition":"CREATE UNIQUE INDEX uq_litigator_global ON public.litigator_suppression_list USING btree (phone_normalized) WHERE (scope = 'global'::text)"},{"name":"uq_litigator_tenant","definition":"CREATE UNIQUE INDEX uq_litigator_tenant ON public.litigator_suppression_list USING btree (phone_normalized, tenant_org_id) WHERE (scope = 'tenant'::text)"}],"policies":[{"cmd":"SELECT","qual":"((scope = 'global'::text) OR ((scope = 'tenant'::text) AND is_tenant_member(tenant_org_id)))","roles":["authenticated"],"tablename":"litigator_suppression_list","permissive":"PERMISSIVE","policyname":"authenticated_view_litigator","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((scope = 'global'::text) AND is_system_admin())","roles":["authenticated"],"tablename":"litigator_suppression_list","permissive":"PERMISSIVE","policyname":"system_admins_manage_global_litigator","schemaname":"public","with_check":"((scope = 'global'::text) AND is_system_admin())"},{"cmd":"ALL","qual":"((scope = 'tenant'::text) AND is_tenant_member(tenant_org_id) AND (is_system_admin() OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.tenant_id)::text = litigator_suppression_list.tenant_org_id) AND (ur.role = ANY (ARRAY['Tenant Owner'::app_role, 'Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))))","roles":["authenticated"],"tablename":"litigator_suppression_list","permissive":"PERMISSIVE","policyname":"tenant_owners_manage_tenant_litigator","schemaname":"public","with_check":"((scope = 'tenant'::text) AND is_tenant_member(tenant_org_id))"}],"triggers":[],"constraints":[{"name":"litigator_suppression_list_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"live_edit_revisions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"route_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"override_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"parent_revision_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"operations","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"live_edit_revisions_pkey","definition":"CREATE UNIQUE INDEX live_edit_revisions_pkey ON public.live_edit_revisions USING btree (id)"},{"name":"live_edit_revisions_tenant_route_created_idx","definition":"CREATE INDEX live_edit_revisions_tenant_route_created_idx ON public.live_edit_revisions USING btree (tenant_id, route_path, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"can_manage_page_override(request_user_id(), (tenant_id)::text)","roles":["authenticated"],"tablename":"live_edit_revisions","permissive":"PERMISSIVE","policyname":"live_edit_revisions_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"live_edit_revisions_operations_check","definition":"CHECK (live_edit_operations_safe(operations))"},{"name":"live_edit_revisions_override_id_fkey","definition":"FOREIGN KEY (override_id) REFERENCES godmode_page_overrides(id) ON DELETE SET NULL"},{"name":"live_edit_revisions_parent_revision_id_fkey","definition":"FOREIGN KEY (parent_revision_id) REFERENCES live_edit_revisions(id) ON DELETE SET NULL"},{"name":"live_edit_revisions_pkey","definition":"PRIMARY KEY (id)"},{"name":"live_edit_revisions_route_path_check","definition":"CHECK (length(route_path) >= 1 AND length(route_path) <= 512)"},{"name":"live_edit_revisions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"live_edit_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"compatibility_tenant_type","type":"text","default":"'*'::text","identity":"","not_null":true,"generated":""},{"name":"route_pattern","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"operations","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"live_edit_templates_compatibility_idx","definition":"CREATE INDEX live_edit_templates_compatibility_idx ON public.live_edit_templates USING btree (compatibility_tenant_type, route_pattern, updated_at DESC)"},{"name":"live_edit_templates_pkey","definition":"CREATE UNIQUE INDEX live_edit_templates_pkey ON public.live_edit_templates USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"\nCASE\n    WHEN (tenant_id IS NULL) THEN is_platform_admin(request_user_id())\n    ELSE can_manage_page_override(request_user_id(), (tenant_id)::text)\nEND","roles":["authenticated"],"tablename":"live_edit_templates","permissive":"PERMISSIVE","policyname":"live_edit_templates_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"live_edit_templates","permissive":"PERMISSIVE","policyname":"live_edit_templates_insert","schemaname":"public","with_check":"\nCASE\n    WHEN (tenant_id IS NULL) THEN is_platform_admin(request_user_id())\n    ELSE can_manage_page_override(request_user_id(), (tenant_id)::text)\nEND"},{"cmd":"SELECT","qual":"((tenant_id IS NULL) OR can_manage_page_override(request_user_id(), (tenant_id)::text))","roles":["authenticated"],"tablename":"live_edit_templates","permissive":"PERMISSIVE","policyname":"live_edit_templates_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"\nCASE\n    WHEN (tenant_id IS NULL) THEN is_platform_admin(request_user_id())\n    ELSE can_manage_page_override(request_user_id(), (tenant_id)::text)\nEND","roles":["authenticated"],"tablename":"live_edit_templates","permissive":"PERMISSIVE","policyname":"live_edit_templates_update","schemaname":"public","with_check":"\nCASE\n    WHEN (tenant_id IS NULL) THEN is_platform_admin(request_user_id())\n    ELSE can_manage_page_override(request_user_id(), (tenant_id)::text)\nEND"}],"triggers":[],"constraints":[{"name":"live_edit_templates_name_check","definition":"CHECK (length(btrim(name)) >= 1 AND length(btrim(name)) <= 120)"},{"name":"live_edit_templates_operations_check","definition":"CHECK (live_edit_operations_safe(operations))"},{"name":"live_edit_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"live_edit_templates_route_pattern_check","definition":"CHECK (length(route_pattern) >= 1 AND length(route_pattern) <= 512)"},{"name":"live_edit_templates_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"live_edit_templates_version_check","definition":"CHECK (version > 0)"}]},{"table":"login_attempts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"success","type":"boolean","default":null,"identity":"","not_null":true,"generated":""},{"name":"failure_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_login_attempts_email","definition":"CREATE INDEX idx_login_attempts_email ON public.login_attempts USING btree (email, created_at DESC)"},{"name":"idx_login_attempts_ip","definition":"CREATE INDEX idx_login_attempts_ip ON public.login_attempts USING btree (ip_address, created_at DESC)"},{"name":"login_attempts_pkey","definition":"CREATE UNIQUE INDEX login_attempts_pkey ON public.login_attempts USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"login_attempts","permissive":"PERMISSIVE","policyname":"platform_admin_view_login_attempts","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"login_attempts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"mail_webhook_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"mailbox_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_event_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_message_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_thread_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload_summary","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mail_webhook_events_message_idx","definition":"CREATE INDEX mail_webhook_events_message_idx ON public.mail_webhook_events USING btree (mailbox_id, provider_message_id) WHERE (provider_message_id IS NOT NULL)"},{"name":"mail_webhook_events_pkey","definition":"CREATE UNIQUE INDEX mail_webhook_events_pkey ON public.mail_webhook_events USING btree (id)"},{"name":"mail_webhook_events_provider_event_key_key","definition":"CREATE UNIQUE INDEX mail_webhook_events_provider_event_key_key ON public.mail_webhook_events USING btree (provider_event_key)"},{"name":"mail_webhook_events_tenant_created_idx","definition":"CREATE INDEX mail_webhook_events_tenant_created_idx ON public.mail_webhook_events USING btree (tenant_org_id, created_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"mail_webhook_events_mailbox_id_fkey","definition":"FOREIGN KEY (mailbox_id) REFERENCES tenant_mailboxes(id) ON DELETE CASCADE"},{"name":"mail_webhook_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"mail_webhook_events_provider_event_key_key","definition":"UNIQUE (provider_event_key)"},{"name":"mail_webhook_events_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"manager_approvals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_request_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"approved_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"manager_approvals_pkey","definition":"CREATE UNIQUE INDEX manager_approvals_pkey ON public.manager_approvals USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"manager_approvals","permissive":"PERMISSIVE","policyname":"manager_approvals_insert","schemaname":"public","with_check":"((is_manager_or_higher_strict(uid(), tenant_id) AND (approved_by = uid())) OR is_platform_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_id, uid()) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"manager_approvals","permissive":"PERMISSIVE","policyname":"manager_approvals_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"manager_approvals_kind_check","definition":"CHECK (kind = ANY (ARRAY['final_completion'::text, 'payroll'::text, 'submission'::text, 'close'::text, 'override'::text, 'dispatch_approval'::text]))"},{"name":"manager_approvals_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"missing_info_leads","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"moved_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"full_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"missing_phone","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"missing_address","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"original_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_missing_info_created","definition":"CREATE INDEX idx_missing_info_created ON public.missing_info_leads USING btree (created_at DESC)"},{"name":"idx_missing_info_status","definition":"CREATE INDEX idx_missing_info_status ON public.missing_info_leads USING btree (status)"},{"name":"missing_info_leads_pkey","definition":"CREATE UNIQUE INDEX missing_info_leads_pkey ON public.missing_info_leads USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"Users insert missing leads","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (missing_info_leads.tenant_org_id)::uuid)))))"},{"cmd":"ALL","qual":"is_system_admin()","roles":["public"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"mil_all","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"missing_leads_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"missing_leads_tenant_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"missing_leads_tenant_update","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), (tenant_org_id)::uuid))"},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (missing_info_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"tenant_users_delete_missing_info","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"tenant_users_insert_missing_info","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (missing_info_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (missing_info_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"tenant_users_update_missing_info","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (missing_info_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (missing_info_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"missing_info_leads","permissive":"PERMISSIVE","policyname":"tenant_users_view_missing_info","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"missing_info_leads_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"mobile_vendor_campaign_recipients","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"provider_message_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"mobile_vendor_campaign_recipients_campaign_idx","definition":"CREATE INDEX mobile_vendor_campaign_recipients_campaign_idx ON public.mobile_vendor_campaign_recipients USING btree (campaign_id, status)"},{"name":"mobile_vendor_campaign_recipients_campaign_member_uq","definition":"CREATE UNIQUE INDEX mobile_vendor_campaign_recipients_campaign_member_uq ON public.mobile_vendor_campaign_recipients USING btree (campaign_id, member_id)"},{"name":"mobile_vendor_campaign_recipients_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_campaign_recipients_pkey ON public.mobile_vendor_campaign_recipients USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_campaign_recipients_campaign_id_fkey","definition":"FOREIGN KEY (campaign_id) REFERENCES mobile_vendor_campaigns(id) ON DELETE CASCADE"},{"name":"mobile_vendor_campaign_recipients_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"mobile_vendor_campaign_recipients_member_id_fkey","definition":"FOREIGN KEY (member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_campaign_recipients_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_campaign_recipients_status_check","definition":"CHECK (status = ANY (ARRAY['queued'::text, 'sent'::text, 'skipped'::text, 'failed'::text]))"},{"name":"mobile_vendor_campaign_recipients_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_type","type":"text","default":"'custom'::text","identity":"","not_null":true,"generated":""},{"name":"audience","type":"text","default":"'next_stop_club_email'::text","identity":"","not_null":true,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"recipient_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"sent_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"skipped_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"failed_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"mobile_vendor_campaigns_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_campaigns_pkey ON public.mobile_vendor_campaigns USING btree (id)"},{"name":"mobile_vendor_campaigns_tenant_idx","definition":"CREATE INDEX mobile_vendor_campaigns_tenant_idx ON public.mobile_vendor_campaigns USING btree (tenant_org_id, created_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_campaigns_campaign_type_check","definition":"CHECK (campaign_type = ANY (ARRAY['next_stop'::text, 'loyalty'::text, 'custom'::text]))"},{"name":"mobile_vendor_campaigns_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_campaigns_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'sending'::text, 'sent'::text, 'partial'::text, 'failed'::text]))"},{"name":"mobile_vendor_campaigns_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_inventory_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"sku","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"item_kind","type":"text","default":"'flavor'::text","identity":"","not_null":true,"generated":""},{"name":"unit","type":"text","default":"'unit'::text","identity":"","not_null":true,"generated":""},{"name":"quantity_on_hand","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"unit_cost","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"units_per_container","type":"numeric(12,2)","default":"1","identity":"","not_null":true,"generated":""},{"name":"reorder_point","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"public_available","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"public_featured","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_inventory_items_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_inventory_items_pkey ON public.mobile_vendor_inventory_items USING btree (id)"},{"name":"mobile_vendor_inventory_items_tenant_kind_idx","definition":"CREATE INDEX mobile_vendor_inventory_items_tenant_kind_idx ON public.mobile_vendor_inventory_items USING btree (tenant_org_id, item_kind, sort_order, name)"},{"name":"mobile_vendor_inventory_items_tenant_org_id_sku_key","definition":"CREATE UNIQUE INDEX mobile_vendor_inventory_items_tenant_org_id_sku_key ON public.mobile_vendor_inventory_items USING btree (tenant_org_id, sku)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"mobile_vendor_inventory_items","permissive":"PERMISSIVE","policyname":"mobile_vendor_inventory_items_tenant_access","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin())"}],"triggers":[],"constraints":[{"name":"mobile_vendor_inventory_items_item_kind_check","definition":"CHECK (item_kind = ANY (ARRAY['flavor'::text, 'supply'::text]))"},{"name":"mobile_vendor_inventory_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_inventory_items_quantity_on_hand_check","definition":"CHECK (quantity_on_hand >= 0::numeric)"},{"name":"mobile_vendor_inventory_items_reorder_point_check","definition":"CHECK (reorder_point >= 0::numeric)"},{"name":"mobile_vendor_inventory_items_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"mobile_vendor_inventory_items_tenant_org_id_sku_key","definition":"UNIQUE (tenant_org_id, sku)"},{"name":"mobile_vendor_inventory_items_unit_cost_check","definition":"CHECK (unit_cost >= 0::numeric)"},{"name":"mobile_vendor_inventory_items_units_per_container_check","definition":"CHECK (units_per_container > 0::numeric)"}]},{"table":"mobile_vendor_inventory_movements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"inventory_item_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"movement_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"quantity_delta","type":"numeric(12,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"balance_after","type":"numeric(12,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"unit_cost_snapshot","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_inventory_movements_event_idx","definition":"CREATE INDEX mobile_vendor_inventory_movements_event_idx ON public.mobile_vendor_inventory_movements USING btree (tenant_org_id, event_booking_id, occurred_at DESC) WHERE (event_booking_id IS NOT NULL)"},{"name":"mobile_vendor_inventory_movements_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_inventory_movements_pkey ON public.mobile_vendor_inventory_movements USING btree (id)"},{"name":"mobile_vendor_inventory_movements_tenant_item_idx","definition":"CREATE INDEX mobile_vendor_inventory_movements_tenant_item_idx ON public.mobile_vendor_inventory_movements USING btree (tenant_org_id, inventory_item_id, occurred_at DESC)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"mobile_vendor_inventory_movements","permissive":"PERMISSIVE","policyname":"mobile_vendor_inventory_movements_tenant_access","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin())"}],"triggers":[],"constraints":[{"name":"mobile_vendor_inventory_movements_balance_after_check","definition":"CHECK (balance_after >= 0::numeric)"},{"name":"mobile_vendor_inventory_movements_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"mobile_vendor_inventory_movements_inventory_item_id_fkey","definition":"FOREIGN KEY (inventory_item_id) REFERENCES mobile_vendor_inventory_items(id) ON DELETE CASCADE"},{"name":"mobile_vendor_inventory_movements_movement_type_check","definition":"CHECK (movement_type = ANY (ARRAY['purchase'::text, 'adjustment'::text, 'event_usage'::text, 'waste'::text]))"},{"name":"mobile_vendor_inventory_movements_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_inventory_movements_quantity_delta_check","definition":"CHECK (quantity_delta <> 0::numeric)"},{"name":"mobile_vendor_inventory_movements_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"mobile_vendor_inventory_movements_unit_cost_snapshot_check","definition":"CHECK (unit_cost_snapshot >= 0::numeric)"}]},{"table":"mobile_vendor_loyalty_activity","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"activity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stamps_delta","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"balance_after","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'knocklaunch'::text","identity":"","not_null":true,"generated":""},{"name":"source_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"points_delta","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"points_balance_after","type":"integer","default":"0","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_loyalty_activity_idempotency_uidx","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_activity_idempotency_uidx ON public.mobile_vendor_loyalty_activity USING btree (tenant_org_id, member_id, activity_type, source, source_ref) WHERE (source_ref IS NOT NULL)"},{"name":"mobile_vendor_loyalty_activity_member_idx","definition":"CREATE INDEX mobile_vendor_loyalty_activity_member_idx ON public.mobile_vendor_loyalty_activity USING btree (member_id, created_at DESC)"},{"name":"mobile_vendor_loyalty_activity_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_activity_pkey ON public.mobile_vendor_loyalty_activity USING btree (id)"},{"name":"mobile_vendor_loyalty_activity_tenant_idx","definition":"CREATE INDEX mobile_vendor_loyalty_activity_tenant_idx ON public.mobile_vendor_loyalty_activity USING btree (tenant_org_id, created_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_activity_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"mobile_vendor_loyalty_activity_member_id_fkey","definition":"FOREIGN KEY (member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_activity_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_activity_tenant_member_fk","definition":"FOREIGN KEY (tenant_org_id, member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_activity_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_loyalty_claims","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_type","type":"text","default":"'photo_moment'::text","identity":"","not_null":true,"generated":""},{"name":"storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"file_size_bytes","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"latitude","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"longitude","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"location_accuracy_m","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"captured_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"submitted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'uploading'::text","identity":"","not_null":true,"generated":""},{"name":"awarded_delta","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"reviewed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"review_note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_mv_loyalty_claims_member","definition":"CREATE INDEX idx_mv_loyalty_claims_member ON public.mobile_vendor_loyalty_claims USING btree (tenant_org_id, member_id, created_at DESC)"},{"name":"idx_mv_loyalty_claims_status","definition":"CREATE INDEX idx_mv_loyalty_claims_status ON public.mobile_vendor_loyalty_claims USING btree (tenant_org_id, status, submitted_at DESC)"},{"name":"mobile_vendor_loyalty_claims_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_claims_pkey ON public.mobile_vendor_loyalty_claims USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_claims_claim_type_check","definition":"CHECK (claim_type = 'photo_moment'::text)"},{"name":"mobile_vendor_loyalty_claims_member_id_fkey","definition":"FOREIGN KEY (member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_claims_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_claims_status_check","definition":"CHECK (status = ANY (ARRAY['uploading'::text, 'pending'::text, 'approved'::text, 'rejected'::text]))"},{"name":"mobile_vendor_loyalty_claims_tenant_member_fk","definition":"FOREIGN KEY (tenant_org_id, member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_claims_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_loyalty_consent_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"consent_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"identity_value","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"capture_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_loyalty_consent_events_idempotency_uidx","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_consent_events_idempotency_uidx ON public.mobile_vendor_loyalty_consent_events USING btree (tenant_org_id, member_id, channel, consent_status, event_ref) WHERE (event_ref IS NOT NULL)"},{"name":"mobile_vendor_loyalty_consent_events_member_idx","definition":"CREATE INDEX mobile_vendor_loyalty_consent_events_member_idx ON public.mobile_vendor_loyalty_consent_events USING btree (tenant_org_id, member_id, occurred_at DESC)"},{"name":"mobile_vendor_loyalty_consent_events_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_consent_events_pkey ON public.mobile_vendor_loyalty_consent_events USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_consent_events_channel_check","definition":"CHECK (channel = ANY (ARRAY['email'::text, 'sms'::text]))"},{"name":"mobile_vendor_loyalty_consent_events_consent_status_check","definition":"CHECK (consent_status = ANY (ARRAY['granted'::text, 'revoked'::text]))"},{"name":"mobile_vendor_loyalty_consent_events_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"mobile_vendor_loyalty_consent_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_consent_events_tenant_member_fk","definition":"FOREIGN KEY (tenant_org_id, member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_consent_events_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_loyalty_login_challenges","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"normalized_email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"code_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"attempts","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"max_attempts","type":"integer","default":"5","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"consumed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_mv_loyalty_login_email_created","definition":"CREATE INDEX idx_mv_loyalty_login_email_created ON public.mobile_vendor_loyalty_login_challenges USING btree (tenant_org_id, normalized_email, created_at DESC)"},{"name":"idx_mv_loyalty_login_expiry","definition":"CREATE INDEX idx_mv_loyalty_login_expiry ON public.mobile_vendor_loyalty_login_challenges USING btree (expires_at)"},{"name":"mobile_vendor_loyalty_login_challenges_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_login_challenges_pkey ON public.mobile_vendor_loyalty_login_challenges USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_login_challenges_attempts_check","definition":"CHECK (attempts >= 0 AND attempts <= 10)"},{"name":"mobile_vendor_loyalty_login_challenges_max_attempts_check","definition":"CHECK (max_attempts >= 1 AND max_attempts <= 10)"},{"name":"mobile_vendor_loyalty_login_challenges_member_id_fkey","definition":"FOREIGN KEY (member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_login_challenges_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_login_challenges_tenant_member_fk","definition":"FOREIGN KEY (tenant_org_id, member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_login_challenges_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_loyalty_members","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"normalized_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"normalized_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"email_opt_in","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"sms_opt_in","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'public_site'::text","identity":"","not_null":true,"generated":""},{"name":"join_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"joined_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"last_visit_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"visits","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"stamp_balance","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"lifetime_stamps","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"rewards_redeemed","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"unsubscribe_token","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"points_balance","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"lifetime_points","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"referral_code","type":"text","default":"upper(substr(replace((gen_random_uuid())::text, '-'::text, ''::text), 1, 10))","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_loyalty_members_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_members_pkey ON public.mobile_vendor_loyalty_members USING btree (id)"},{"name":"mobile_vendor_loyalty_members_tenant_contact_uq","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_members_tenant_contact_uq ON public.mobile_vendor_loyalty_members USING btree (tenant_org_id, contact_id) WHERE (contact_id IS NOT NULL)"},{"name":"mobile_vendor_loyalty_members_tenant_email_uq","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_members_tenant_email_uq ON public.mobile_vendor_loyalty_members USING btree (tenant_org_id, normalized_email) WHERE (normalized_email IS NOT NULL)"},{"name":"mobile_vendor_loyalty_members_tenant_id_unique","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_members_tenant_id_unique ON public.mobile_vendor_loyalty_members USING btree (tenant_org_id, id)"},{"name":"mobile_vendor_loyalty_members_tenant_referral_code_uidx","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_members_tenant_referral_code_uidx ON public.mobile_vendor_loyalty_members USING btree (tenant_org_id, referral_code)"},{"name":"mobile_vendor_loyalty_members_tenant_status_idx","definition":"CREATE INDEX mobile_vendor_loyalty_members_tenant_status_idx ON public.mobile_vendor_loyalty_members USING btree (tenant_org_id, status, joined_at DESC)"},{"name":"mobile_vendor_loyalty_members_unsubscribe_uq","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_members_unsubscribe_uq ON public.mobile_vendor_loyalty_members USING btree (unsubscribe_token)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_members_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"mobile_vendor_loyalty_members_lifetime_points_nonnegative","definition":"CHECK (lifetime_points >= 0)"},{"name":"mobile_vendor_loyalty_members_lifetime_stamps_check","definition":"CHECK (lifetime_stamps >= 0)"},{"name":"mobile_vendor_loyalty_members_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_members_points_balance_nonnegative","definition":"CHECK (points_balance >= 0)"},{"name":"mobile_vendor_loyalty_members_points_not_above_lifetime","definition":"CHECK (points_balance <= lifetime_points)"},{"name":"mobile_vendor_loyalty_members_rewards_redeemed_check","definition":"CHECK (rewards_redeemed >= 0)"},{"name":"mobile_vendor_loyalty_members_stamp_balance_check","definition":"CHECK (stamp_balance >= 0)"},{"name":"mobile_vendor_loyalty_members_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'unsubscribed'::text]))"},{"name":"mobile_vendor_loyalty_members_tenant_id_unique","definition":"UNIQUE (tenant_org_id, id)"},{"name":"mobile_vendor_loyalty_members_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_members_visits_check","definition":"CHECK (visits >= 0)"}]},{"table":"mobile_vendor_loyalty_purchases","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"purchase_ref","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"payment_method","type":"text","default":"'cash'::text","identity":"","not_null":true,"generated":""},{"name":"amount_cents","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"currency","type":"text","default":"'USD'::text","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'owner_action'::text","identity":"","not_null":true,"generated":""},{"name":"source_transaction_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'confirmed'::text","identity":"","not_null":true,"generated":""},{"name":"confirmed_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_loyalty_purchases_member_occurred_idx","definition":"CREATE INDEX mobile_vendor_loyalty_purchases_member_occurred_idx ON public.mobile_vendor_loyalty_purchases USING btree (tenant_org_id, member_id, occurred_at DESC)"},{"name":"mobile_vendor_loyalty_purchases_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_purchases_pkey ON public.mobile_vendor_loyalty_purchases USING btree (id)"},{"name":"mobile_vendor_loyalty_purchases_source_transaction_key","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_purchases_source_transaction_key ON public.mobile_vendor_loyalty_purchases USING btree (tenant_org_id, payment_method, source_transaction_id) WHERE (source_transaction_id IS NOT NULL)"},{"name":"mobile_vendor_loyalty_purchases_tenant_ref_key","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_purchases_tenant_ref_key ON public.mobile_vendor_loyalty_purchases USING btree (tenant_org_id, purchase_ref)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_purchases_amount_cents_check","definition":"CHECK (amount_cents IS NULL OR amount_cents >= 0)"},{"name":"mobile_vendor_loyalty_purchases_confirmed_by_user_id_fkey","definition":"FOREIGN KEY (confirmed_by_user_id) REFERENCES users(id) ON DELETE SET NULL"},{"name":"mobile_vendor_loyalty_purchases_currency_check","definition":"CHECK (char_length(currency) = 3)"},{"name":"mobile_vendor_loyalty_purchases_payment_method_check","definition":"CHECK (payment_method = ANY (ARRAY['cash'::text, 'square'::text, 'other'::text]))"},{"name":"mobile_vendor_loyalty_purchases_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_purchases_source_check","definition":"CHECK (btrim(source) <> ''::text)"},{"name":"mobile_vendor_loyalty_purchases_status_check","definition":"CHECK (status = ANY (ARRAY['confirmed'::text, 'voided'::text]))"},{"name":"mobile_vendor_loyalty_purchases_tenant_member_fk","definition":"FOREIGN KEY (tenant_org_id, member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_purchases_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_purchases_tenant_ref_key","definition":"UNIQUE (tenant_org_id, purchase_ref)"}]},{"table":"mobile_vendor_loyalty_referrals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"referrer_member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"friend_member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"referral_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'joined'::text","identity":"","not_null":true,"generated":""},{"name":"joined_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"first_purchase_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer_points_awarded","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"referrer_points_awarded_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"welcome_reward_status","type":"text","default":"'pending_return'::text","identity":"","not_null":true,"generated":""},{"name":"welcome_unlocked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"welcome_redeemed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"first_purchase_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"first_purchase_source","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"mobile_vendor_loyalty_referrals_one_friend","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_referrals_one_friend ON public.mobile_vendor_loyalty_referrals USING btree (tenant_org_id, friend_member_id)"},{"name":"mobile_vendor_loyalty_referrals_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_referrals_pkey ON public.mobile_vendor_loyalty_referrals USING btree (id)"},{"name":"mobile_vendor_loyalty_referrals_referrer_idx","definition":"CREATE INDEX mobile_vendor_loyalty_referrals_referrer_idx ON public.mobile_vendor_loyalty_referrals USING btree (tenant_org_id, referrer_member_id, created_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_referrals_friend_member_id_fkey","definition":"FOREIGN KEY (friend_member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_referrals_no_self","definition":"CHECK (referrer_member_id <> friend_member_id)"},{"name":"mobile_vendor_loyalty_referrals_one_friend","definition":"UNIQUE (tenant_org_id, friend_member_id)"},{"name":"mobile_vendor_loyalty_referrals_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_referrals_referrer_member_id_fkey","definition":"FOREIGN KEY (referrer_member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_referrals_status_check","definition":"CHECK (status = ANY (ARRAY['joined'::text, 'purchase_confirmed'::text, 'welcome_ready'::text, 'completed'::text]))"},{"name":"mobile_vendor_loyalty_referrals_tenant_friend_fk","definition":"FOREIGN KEY (tenant_org_id, friend_member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_referrals_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_referrals_tenant_referrer_fk","definition":"FOREIGN KEY (tenant_org_id, referrer_member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_referrals_welcome_reward_status_check","definition":"CHECK (welcome_reward_status = ANY (ARRAY['pending_return'::text, 'ready'::text, 'redeemed'::text]))"}]},{"table":"mobile_vendor_loyalty_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"member_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_seen_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_mv_loyalty_sessions_expiry","definition":"CREATE INDEX idx_mv_loyalty_sessions_expiry ON public.mobile_vendor_loyalty_sessions USING btree (expires_at)"},{"name":"idx_mv_loyalty_sessions_member","definition":"CREATE INDEX idx_mv_loyalty_sessions_member ON public.mobile_vendor_loyalty_sessions USING btree (tenant_org_id, member_id, created_at DESC)"},{"name":"mobile_vendor_loyalty_sessions_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_sessions_pkey ON public.mobile_vendor_loyalty_sessions USING btree (id)"},{"name":"mobile_vendor_loyalty_sessions_token_hash_key","definition":"CREATE UNIQUE INDEX mobile_vendor_loyalty_sessions_token_hash_key ON public.mobile_vendor_loyalty_sessions USING btree (token_hash)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_loyalty_sessions_member_id_fkey","definition":"FOREIGN KEY (member_id) REFERENCES mobile_vendor_loyalty_members(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_loyalty_sessions_tenant_member_fk","definition":"FOREIGN KEY (tenant_org_id, member_id) REFERENCES mobile_vendor_loyalty_members(tenant_org_id, id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_sessions_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"mobile_vendor_loyalty_sessions_token_hash_key","definition":"UNIQUE (token_hash)"}]},{"table":"mobile_vendor_proposal_sequences","schema":"public","columns":[{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"proposal_year","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"last_sequence","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_proposal_sequences_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_proposal_sequences_pkey ON public.mobile_vendor_proposal_sequences USING btree (tenant_org_id, proposal_year)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_proposal_sequences_last_sequence_check","definition":"CHECK (last_sequence >= 0)"},{"name":"mobile_vendor_proposal_sequences_pkey","definition":"PRIMARY KEY (tenant_org_id, proposal_year)"},{"name":"mobile_vendor_proposal_sequences_proposal_year_check","definition":"CHECK (proposal_year >= 2000 AND proposal_year <= 2200)"},{"name":"mobile_vendor_proposal_sequences_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mobile_vendor_schedule_imports","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'uploading'::text","identity":"","not_null":true,"generated":""},{"name":"source_files","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"extracted_events","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"reviewed_events","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"warnings","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"model","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"default_year","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_booking_ids","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"skipped_duplicates","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"error_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"extracted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"committed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"failed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mobile_vendor_schedule_imports_owner_pending_idx","definition":"CREATE INDEX mobile_vendor_schedule_imports_owner_pending_idx ON public.mobile_vendor_schedule_imports USING btree (tenant_org_id, created_by, status, created_at DESC)"},{"name":"mobile_vendor_schedule_imports_pkey","definition":"CREATE UNIQUE INDEX mobile_vendor_schedule_imports_pkey ON public.mobile_vendor_schedule_imports USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"mobile_vendor_schedule_imports_pkey","definition":"PRIMARY KEY (id)"},{"name":"mobile_vendor_schedule_imports_skipped_duplicates_check","definition":"CHECK (skipped_duplicates >= 0)"},{"name":"mobile_vendor_schedule_imports_status_check","definition":"CHECK (status = ANY (ARRAY['uploading'::text, 'extracted'::text, 'committed'::text, 'duplicate'::text, 'failed'::text]))"},{"name":"mobile_vendor_schedule_imports_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"mode_change_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"from_mode","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_mode","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_by_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"mode_change_log_pkey","definition":"CREATE UNIQUE INDEX mode_change_log_pkey ON public.mode_change_log USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"mode_change_log","permissive":"PERMISSIVE","policyname":"Only GodMode can insert mode log","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"mode_change_log","permissive":"PERMISSIVE","policyname":"System admins read mode log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"mode_change_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"nav_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"route","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"icon","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"roles","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"tenant_types","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_nav_items_order_index","definition":"CREATE INDEX idx_nav_items_order_index ON public.nav_items USING btree (order_index)"},{"name":"idx_nav_items_tenant_org_id","definition":"CREATE INDEX idx_nav_items_tenant_org_id ON public.nav_items USING btree (tenant_org_id)"},{"name":"nav_items_pkey","definition":"CREATE UNIQUE INDEX nav_items_pkey ON public.nav_items USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((is_active = true) AND ((tenant_org_id IS NULL) OR is_tenant_member(tenant_org_id) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"nav_items","permissive":"PERMISSIVE","policyname":"Users view active nav items in their tenant","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"nav_items","permissive":"PERMISSIVE","policyname":"platform_admin_manage_nav_items","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"nav_items_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"needs_skiptrace","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"moved_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"original_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'Pending Skiptrace'::text","identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"moved_back_to_lead_deck","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":"'No name extracted from document'::text","identity":"","not_null":true,"generated":""},{"name":"source_file","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"moved_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"skiptrace_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_needs_skiptrace_status","definition":"CREATE INDEX idx_needs_skiptrace_status ON public.needs_skiptrace USING btree (status)"},{"name":"idx_needs_skiptrace_tenant","definition":"CREATE INDEX idx_needs_skiptrace_tenant ON public.needs_skiptrace USING btree (tenant_org_id)"},{"name":"needs_skiptrace_pkey","definition":"CREATE UNIQUE INDEX needs_skiptrace_pkey ON public.needs_skiptrace USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = needs_skiptrace.tenant_org_id))))","roles":["public"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"Users view tenant skiptrace leads","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin()","roles":["public"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"ns_all","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"skiptrace_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"skiptrace_tenant_owner_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))"},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (needs_skiptrace.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"tenant_users_delete_skiptrace","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"tenant_users_insert_skiptrace","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (needs_skiptrace.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (needs_skiptrace.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"tenant_users_update_skiptrace","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (needs_skiptrace.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (needs_skiptrace.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"needs_skiptrace","permissive":"PERMISSIVE","policyname":"tenant_users_view_skiptrace","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"needs_skiptrace_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"new_roofs_queue","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_finaled_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_age_years","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"moved_to_queue_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"moved_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":"'Recent roof permit'::text","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":false,"generated":""},{"name":"reviewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_new_roofs_queue_lead","definition":"CREATE INDEX idx_new_roofs_queue_lead ON public.new_roofs_queue USING btree (lead_id)"},{"name":"idx_new_roofs_queue_tenant","definition":"CREATE INDEX idx_new_roofs_queue_tenant ON public.new_roofs_queue USING btree (tenant_org_id, status)"},{"name":"new_roofs_queue_lead_id_tenant_org_id_key","definition":"CREATE UNIQUE INDEX new_roofs_queue_lead_id_tenant_org_id_key ON public.new_roofs_queue USING btree (lead_id, tenant_org_id)"},{"name":"new_roofs_queue_pkey","definition":"CREATE UNIQUE INDEX new_roofs_queue_pkey ON public.new_roofs_queue USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = new_roofs_queue.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Admin'::app_role, 'GodMode'::app_role, 'Owner'::app_role])))))","roles":["public"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"Admins manage new roofs queue","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = new_roofs_queue.tenant_org_id))))","roles":["public"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"Users view tenant new roofs queue","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin()","roles":["public"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"nrq_all","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (new_roofs_queue.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"tenant_users_delete_new_roofs","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"tenant_users_insert_new_roofs","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (new_roofs_queue.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (new_roofs_queue.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"tenant_users_update_new_roofs","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (new_roofs_queue.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (new_roofs_queue.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"new_roofs_queue","permissive":"PERMISSIVE","policyname":"tenant_users_view_new_roofs","schemaname":"public","with_check":null}],"triggers":[{"name":"new_roofs_queue_updated_at","definition":"CREATE TRIGGER new_roofs_queue_updated_at BEFORE UPDATE ON new_roofs_queue FOR EACH ROW EXECUTE FUNCTION update_new_roofs_queue_updated_at()"}],"constraints":[{"name":"new_roofs_queue_lead_id_tenant_org_id_key","definition":"UNIQUE (lead_id, tenant_org_id)"},{"name":"new_roofs_queue_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"notes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"gid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"note","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'preworkflow'::text","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_notes_lead_id","definition":"CREATE INDEX idx_notes_lead_id ON public.notes USING btree (lead_id)"},{"name":"notes_pkey","definition":"CREATE UNIQUE INDEX notes_pkey ON public.notes USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(rep_email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text)","roles":["authenticated"],"tablename":"notes","permissive":"PERMISSIVE","policyname":"Users can delete own notes","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(rep_email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text)","roles":["authenticated"],"tablename":"notes","permissive":"PERMISSIVE","policyname":"Users can update own notes","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((rep_email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text) OR (EXISTS ( SELECT 1\n   FROM (lead_deck ld\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = ld.tenant_org_id)))\n  WHERE ((ld.lead_id = notes.lead_id) AND (utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"notes","permissive":"PERMISSIVE","policyname":"Users can view own or tenant notes","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"false","roles":["public"],"tablename":"notes","permissive":"PERMISSIVE","policyname":"deny all","schemaname":"public","with_check":"false"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"notes","permissive":"PERMISSIVE","policyname":"users_insert_tenant_notes","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (lead_deck ld\n     JOIN security_active_user_tenant_memberships utm ON (((utm.tenant_id)::text = ld.tenant_org_id)))\n  WHERE ((ld.lead_id = notes.lead_id) AND (utm.user_id = uid()) AND (utm.status = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"notes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"notification_preferences","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"in_app_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"email_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"sms_enabled","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"frequency","type":"text","default":"'instant'::text","identity":"","not_null":true,"generated":""},{"name":"quiet_hours_start","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"quiet_hours_end","type":"time without time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_notif_prefs_user","definition":"CREATE INDEX idx_notif_prefs_user ON public.notification_preferences USING btree (user_id)"},{"name":"notification_preferences_pkey","definition":"CREATE UNIQUE INDEX notification_preferences_pkey ON public.notification_preferences USING btree (id)"},{"name":"notification_preferences_user_id_event_type_key","definition":"CREATE UNIQUE INDEX notification_preferences_user_id_event_type_key ON public.notification_preferences USING btree (user_id, event_type)"}],"policies":[{"cmd":"DELETE","qual":"(uid() = user_id)","roles":["public"],"tablename":"notification_preferences","permissive":"PERMISSIVE","policyname":"Users delete their own notification prefs","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"notification_preferences","permissive":"PERMISSIVE","policyname":"Users insert their own notification prefs","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["public"],"tablename":"notification_preferences","permissive":"PERMISSIVE","policyname":"Users update their own notification prefs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"notification_preferences","permissive":"PERMISSIVE","policyname":"Users view their own notification prefs","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_notif_prefs_updated_at","definition":"CREATE TRIGGER trg_notif_prefs_updated_at BEFORE UPDATE ON notification_preferences FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"notification_preferences_pkey","definition":"PRIMARY KEY (id)"},{"name":"notification_preferences_user_id_event_type_key","definition":"UNIQUE (user_id, event_type)"},{"name":"valid_frequency","definition":"CHECK (frequency = ANY (ARRAY['instant'::text, 'hourly_digest'::text, 'daily_digest'::text, 'never'::text]))"}]},{"table":"notification_queue","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notification_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"severity","type":"text","default":"'info'::text","identity":"","not_null":false,"generated":""},{"name":"read","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"action_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"read_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_notification_created","definition":"CREATE INDEX idx_notification_created ON public.notification_queue USING btree (created_at DESC)"},{"name":"idx_notification_read","definition":"CREATE INDEX idx_notification_read ON public.notification_queue USING btree (read)"},{"name":"idx_notification_user_id","definition":"CREATE INDEX idx_notification_user_id ON public.notification_queue USING btree (user_id)"},{"name":"notification_queue_pkey","definition":"CREATE UNIQUE INDEX notification_queue_pkey ON public.notification_queue USING btree (id)"},{"name":"notification_queue_unique_per_jobreq_user","definition":"CREATE UNIQUE INDEX notification_queue_unique_per_jobreq_user ON public.notification_queue USING btree (user_id, notification_type, ((metadata ->> 'job_request_id'::text))) WHERE (notification_type = 'job_request_pending'::text)"}],"policies":[{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"notification_queue","permissive":"PERMISSIVE","policyname":"Users can update own notifications","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"notification_queue","permissive":"PERMISSIVE","policyname":"Users can view own notifications","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"notification_queue","permissive":"PERMISSIVE","policyname":"platform_admin_insert_notifications","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"notification_queue_pkey","definition":"PRIMARY KEY (id)"},{"name":"notification_queue_severity_check","definition":"CHECK (severity = ANY (ARRAY['info'::text, 'warning'::text, 'critical'::text]))"}]},{"table":"notifications","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"link","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"read_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_notifications_unread","definition":"CREATE INDEX idx_notifications_unread ON public.notifications USING btree (user_id) WHERE (read_at IS NULL)"},{"name":"idx_notifications_user_id","definition":"CREATE INDEX idx_notifications_user_id ON public.notifications USING btree (user_id)"},{"name":"notifications_pkey","definition":"CREATE UNIQUE INDEX notifications_pkey ON public.notifications USING btree (id)"},{"name":"notifications_unique_per_jobreq_user","definition":"CREATE UNIQUE INDEX notifications_unique_per_jobreq_user ON public.notifications USING btree (user_id, type, ((metadata ->> 'job_request_id'::text))) WHERE (type = 'job_request_pending'::text)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["service_role"],"tablename":"notifications","permissive":"PERMISSIVE","policyname":"Service role can insert notifications","schemaname":"public","with_check":"true"},{"cmd":"UPDATE","qual":"(( SELECT uid() AS uid) = user_id)","roles":["public"],"tablename":"notifications","permissive":"PERMISSIVE","policyname":"Users can update their own notifications","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(( SELECT uid() AS uid) = user_id)","roles":["public"],"tablename":"notifications","permissive":"PERMISSIVE","policyname":"Users can view their own notifications","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"notifications","permissive":"PERMISSIVE","policyname":"authenticated_insert_notifications","schemaname":"public","with_check":"(( SELECT uid() AS uid) IS NOT NULL)"}],"triggers":[],"constraints":[{"name":"notifications_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ocr_jobs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"total_files","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"processed_files","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"ocr_progress","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"results","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"ocr_jobs_pkey","definition":"CREATE UNIQUE INDEX ocr_jobs_pkey ON public.ocr_jobs USING btree (id)"},{"name":"ocr_jobs_user_id_idx","definition":"CREATE INDEX ocr_jobs_user_id_idx ON public.ocr_jobs USING btree (user_id, created_at DESC)"}],"policies":[{"cmd":"DELETE","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"ocr_jobs","permissive":"PERMISSIVE","policyname":"Users manage own OCR jobs - delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"ocr_jobs","permissive":"PERMISSIVE","policyname":"Users manage own OCR jobs - insert","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"ocr_jobs","permissive":"PERMISSIVE","policyname":"Users manage own OCR jobs - select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"ocr_jobs","permissive":"PERMISSIVE","policyname":"Users manage own OCR jobs - update","schemaname":"public","with_check":"(uid() = user_id)"}],"triggers":[{"name":"ocr_jobs_set_updated_at","definition":"CREATE TRIGGER ocr_jobs_set_updated_at BEFORE UPDATE ON ocr_jobs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"ocr_jobs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"offline_sync_queue","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"operation_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"table_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"record_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"data","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"synced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_offline_sync_queue_status","definition":"CREATE INDEX idx_offline_sync_queue_status ON public.offline_sync_queue USING btree (status)"},{"name":"idx_offline_sync_queue_user_id","definition":"CREATE INDEX idx_offline_sync_queue_user_id ON public.offline_sync_queue USING btree (user_id)"},{"name":"offline_sync_queue_pkey","definition":"CREATE UNIQUE INDEX offline_sync_queue_pkey ON public.offline_sync_queue USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(uid() = user_id)","roles":["public"],"tablename":"offline_sync_queue","permissive":"PERMISSIVE","policyname":"Users manage their sync queue","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"offline_sync_queue_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"onboarding_email_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"template_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'invitation'::text","identity":"","not_null":false,"generated":""},{"name":"variables","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"onboarding_email_templates_pkey","definition":"CREATE UNIQUE INDEX onboarding_email_templates_pkey ON public.onboarding_email_templates USING btree (id)"},{"name":"onboarding_email_templates_template_key_key","definition":"CREATE UNIQUE INDEX onboarding_email_templates_template_key_key ON public.onboarding_email_templates USING btree (template_key)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"onboarding_email_templates","permissive":"PERMISSIVE","policyname":"Authenticated users can view templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"onboarding_email_templates","permissive":"PERMISSIVE","policyname":"system_admins_manage_templates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"update_onboarding_email_templates_updated_at","definition":"CREATE TRIGGER update_onboarding_email_templates_updated_at BEFORE UPDATE ON onboarding_email_templates FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"onboarding_email_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"onboarding_email_templates_template_key_key","definition":"UNIQUE (template_key)"}]},{"table":"onboarding_license_sources","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"jurisdiction","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"business_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"is_official","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"onboarding_license_sources_jurisdiction_business_type_provi_key","definition":"CREATE UNIQUE INDEX onboarding_license_sources_jurisdiction_business_type_provi_key ON public.onboarding_license_sources USING btree (jurisdiction, business_type, provider_key)"},{"name":"onboarding_license_sources_pkey","definition":"CREATE UNIQUE INDEX onboarding_license_sources_pkey ON public.onboarding_license_sources USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"onboarding_license_sources","permissive":"PERMISSIVE","policyname":"onboarding_license_sources_platform_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"onboarding_license_sources","permissive":"PERMISSIVE","policyname":"onboarding_license_sources_platform_write","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"onboarding_license_sources_jurisdiction_business_type_provi_key","definition":"UNIQUE (jurisdiction, business_type, provider_key)"},{"name":"onboarding_license_sources_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"onboarding_research_tasks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"research_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"jurisdiction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"query","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"result","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"dispatch_token","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"dispatched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_onboarding_research_session","definition":"CREATE INDEX idx_onboarding_research_session ON public.onboarding_research_tasks USING btree (session_id, status)"},{"name":"onboarding_research_tasks_pkey","definition":"CREATE UNIQUE INDEX onboarding_research_tasks_pkey ON public.onboarding_research_tasks USING btree (id)"},{"name":"uq_onboarding_research_task_scope","definition":"CREATE UNIQUE INDEX uq_onboarding_research_task_scope ON public.onboarding_research_tasks USING btree (session_id, research_type, jurisdiction)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"onboarding_research_tasks","permissive":"PERMISSIVE","policyname":"onboarding_research_admin_manage","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM onboarding_sessions s\n  WHERE ((s.id = onboarding_research_tasks.session_id) AND (s.owner_user_id = uid())))))","roles":["public"],"tablename":"onboarding_research_tasks","permissive":"PERMISSIVE","policyname":"onboarding_research_owner_select","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_dispatch_onboarding_research_task","definition":"CREATE TRIGGER trg_dispatch_onboarding_research_task AFTER INSERT OR UPDATE OF status, dispatch_token, provider_key ON onboarding_research_tasks FOR EACH ROW EXECUTE FUNCTION dispatch_onboarding_research_task()"}],"constraints":[{"name":"onboarding_research_tasks_pkey","definition":"PRIMARY KEY (id)"},{"name":"onboarding_research_tasks_session_id_fkey","definition":"FOREIGN KEY (session_id) REFERENCES onboarding_sessions(id) ON DELETE CASCADE"},{"name":"onboarding_research_tasks_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'running'::text, 'verified'::text, 'not_found'::text, 'needs_review'::text, 'failed'::text, 'skipped'::text]))"}]},{"table":"onboarding_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"owner_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"company_slug","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_business_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"canonical_tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_lines","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"operating_states","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"service_area","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"team_size","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"goals","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"requested_capabilities","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"intake_answers","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"research_state","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"derived_blueprint","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"readiness","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"last_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_onboarding_sessions_owner","definition":"CREATE INDEX idx_onboarding_sessions_owner ON public.onboarding_sessions USING btree (owner_user_id, created_at DESC)"},{"name":"idx_onboarding_sessions_status","definition":"CREATE INDEX idx_onboarding_sessions_status ON public.onboarding_sessions USING btree (status, updated_at DESC)"},{"name":"onboarding_sessions_pkey","definition":"CREATE UNIQUE INDEX onboarding_sessions_pkey ON public.onboarding_sessions USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"onboarding_sessions","permissive":"PERMISSIVE","policyname":"onboarding_sessions_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"onboarding_sessions","permissive":"PERMISSIVE","policyname":"onboarding_sessions_owner_insert","schemaname":"public","with_check":"((owner_user_id = uid()) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((owner_user_id = uid()) OR is_system_admin(uid()))","roles":["public"],"tablename":"onboarding_sessions","permissive":"PERMISSIVE","policyname":"onboarding_sessions_owner_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((owner_user_id = uid()) OR is_system_admin(uid()))","roles":["public"],"tablename":"onboarding_sessions","permissive":"PERMISSIVE","policyname":"onboarding_sessions_owner_update","schemaname":"public","with_check":"((owner_user_id = uid()) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"onboarding_sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"onboarding_sessions_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'intake'::text, 'researching'::text, 'validating'::text, 'needs_input'::text, 'ready_to_provision'::text, 'provisioning'::text, 'ready'::text, 'live'::text, 'blocked'::text, 'failed'::text, 'cancelled'::text]))"},{"name":"onboarding_sessions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE SET NULL"}]},{"table":"opportunity_radar_opportunities","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_kind","type":"text","default":"'public_web'::text","identity":"","not_null":true,"generated":""},{"name":"source_external_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"excerpt","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"intent_score","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"confidence","type":"numeric(5,4)","default":"0","identity":"","not_null":true,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"posted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"captured_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'new'::text","identity":"","not_null":true,"generated":""},{"name":"dedupe_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provenance","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_opportunity_radar_tenant_captured","definition":"CREATE INDEX idx_opportunity_radar_tenant_captured ON public.opportunity_radar_opportunities USING btree (tenant_id, captured_at DESC)"},{"name":"idx_opportunity_radar_tenant_status","definition":"CREATE INDEX idx_opportunity_radar_tenant_status ON public.opportunity_radar_opportunities USING btree (tenant_id, status, intent_score DESC)"},{"name":"opportunity_radar_opportunities_pkey","definition":"CREATE UNIQUE INDEX opportunity_radar_opportunities_pkey ON public.opportunity_radar_opportunities USING btree (id)"},{"name":"opportunity_radar_opportunities_tenant_id_dedupe_key_key","definition":"CREATE UNIQUE INDEX opportunity_radar_opportunities_tenant_id_dedupe_key_key ON public.opportunity_radar_opportunities USING btree (tenant_id, dedupe_key)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"opportunity_radar_opportunities","permissive":"PERMISSIVE","policyname":"opportunity_radar_opportunities_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"opportunity_radar_opportunities","permissive":"PERMISSIVE","policyname":"opportunity_radar_opportunities_insert","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"opportunity_radar_opportunities","permissive":"PERMISSIVE","policyname":"opportunity_radar_opportunities_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"opportunity_radar_opportunities","permissive":"PERMISSIVE","policyname":"opportunity_radar_opportunities_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_opportunity_radar_updated_at","definition":"CREATE TRIGGER trg_opportunity_radar_updated_at BEFORE UPDATE ON opportunity_radar_opportunities FOR EACH ROW EXECUTE FUNCTION touch_opportunity_radar_updated_at()"}],"constraints":[{"name":"opportunity_radar_opportunities_confidence_check","definition":"CHECK (confidence >= 0::numeric AND confidence <= 1::numeric)"},{"name":"opportunity_radar_opportunities_intent_score_check","definition":"CHECK (intent_score >= 0 AND intent_score <= 100)"},{"name":"opportunity_radar_opportunities_pkey","definition":"PRIMARY KEY (id)"},{"name":"opportunity_radar_opportunities_status_check","definition":"CHECK (status = ANY (ARRAY['new'::text, 'saved'::text, 'dismissed'::text, 'converted'::text]))"},{"name":"opportunity_radar_opportunities_tenant_id_dedupe_key_key","definition":"UNIQUE (tenant_id, dedupe_key)"},{"name":"opportunity_radar_opportunities_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"opportunity_radar_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"anchor_zip","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"anchor_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'running'::text","identity":"","not_null":true,"generated":""},{"name":"source_summary","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"discovered_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"inserted_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_opportunity_radar_runs_tenant_started","definition":"CREATE INDEX idx_opportunity_radar_runs_tenant_started ON public.opportunity_radar_runs USING btree (tenant_id, started_at DESC)"},{"name":"opportunity_radar_runs_pkey","definition":"CREATE UNIQUE INDEX opportunity_radar_runs_pkey ON public.opportunity_radar_runs USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"opportunity_radar_runs","permissive":"PERMISSIVE","policyname":"opportunity_radar_runs_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"opportunity_radar_runs_pkey","definition":"PRIMARY KEY (id)"},{"name":"opportunity_radar_runs_status_check","definition":"CHECK (status = ANY (ARRAY['running'::text, 'complete'::text, 'failed'::text, 'skipped'::text]))"},{"name":"opportunity_radar_runs_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"owner_workspace_notes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"pinned","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"source_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"dismissed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"owner_workspace_notes_pkey","definition":"CREATE UNIQUE INDEX owner_workspace_notes_pkey ON public.owner_workspace_notes USING btree (id)"},{"name":"owner_workspace_notes_source_uidx","definition":"CREATE UNIQUE INDEX owner_workspace_notes_source_uidx ON public.owner_workspace_notes USING btree (tenant_id, source_type, source_id) WHERE ((source_type IS NOT NULL) AND (source_id IS NOT NULL))"},{"name":"owner_workspace_notes_tenant_updated_idx","definition":"CREATE INDEX owner_workspace_notes_tenant_updated_idx ON public.owner_workspace_notes USING btree (tenant_id, pinned DESC, updated_at DESC)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_id) OR is_system_admin())","roles":["public"],"tablename":"owner_workspace_notes","permissive":"PERMISSIVE","policyname":"owner_workspace_notes_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"owner_workspace_notes","permissive":"PERMISSIVE","policyname":"owner_workspace_notes_insert","schemaname":"public","with_check":"((uid() = user_id) AND (is_tenant_member(tenant_id) OR is_system_admin()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_id) OR is_system_admin())","roles":["public"],"tablename":"owner_workspace_notes","permissive":"PERMISSIVE","policyname":"owner_workspace_notes_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_id) OR is_system_admin())","roles":["public"],"tablename":"owner_workspace_notes","permissive":"PERMISSIVE","policyname":"owner_workspace_notes_update","schemaname":"public","with_check":"(is_tenant_member(tenant_id) OR is_system_admin())"}],"triggers":[],"constraints":[{"name":"owner_workspace_notes_pkey","definition":"PRIMARY KEY (id)"},{"name":"owner_workspace_notes_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"pa_carrier_estimate_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"valuation_item_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"item_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"quantity","type":"numeric","default":"1","identity":"","not_null":true,"generated":""},{"name":"unit","type":"text","default":"'EA'::text","identity":"","not_null":true,"generated":""},{"name":"unit_price","type":"numeric","default":"0","identity":"","not_null":true,"generated":""},{"name":"total","type":"numeric","default":"(quantity * unit_price)","identity":"","not_null":false,"generated":"s"},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"evidence_doc_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":"uid()","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pa_carrier_estimate_items_claim","definition":"CREATE INDEX idx_pa_carrier_estimate_items_claim ON public.pa_carrier_estimate_items USING btree (tenant_org_id, claim_id)"},{"name":"idx_pa_carrier_estimate_items_valuation","definition":"CREATE INDEX idx_pa_carrier_estimate_items_valuation ON public.pa_carrier_estimate_items USING btree (valuation_item_id) WHERE (valuation_item_id IS NOT NULL)"},{"name":"pa_carrier_estimate_items_pkey","definition":"CREATE UNIQUE INDEX pa_carrier_estimate_items_pkey ON public.pa_carrier_estimate_items USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"pa_carrier_estimate_items","permissive":"PERMISSIVE","policyname":"Tenant members can create PA carrier estimate items","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"DELETE","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"pa_carrier_estimate_items","permissive":"PERMISSIVE","policyname":"Tenant members can delete PA carrier estimate items","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"pa_carrier_estimate_items","permissive":"PERMISSIVE","policyname":"Tenant members can update PA carrier estimate items","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"pa_carrier_estimate_items","permissive":"PERMISSIVE","policyname":"Tenant members can view PA carrier estimate items","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"pa_carrier_estimate_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"pa_carrier_estimate_items_quantity_check","definition":"CHECK (quantity >= 0::numeric)"},{"name":"pa_carrier_estimate_items_unit_price_check","definition":"CHECK (unit_price >= 0::numeric)"},{"name":"pa_carrier_estimate_items_valuation_item_id_fkey","definition":"FOREIGN KEY (valuation_item_id) REFERENCES claim_valuation_items(id) ON DELETE SET NULL"}]},{"table":"pa_clients","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"client_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_company","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'Active'::text","identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"pa_clients_client_id_key","definition":"CREATE UNIQUE INDEX pa_clients_client_id_key ON public.pa_clients USING btree (client_id)"},{"name":"pa_clients_pkey","definition":"CREATE UNIQUE INDEX pa_clients_pkey ON public.pa_clients USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = pa_clients.tenant_org_id))))","roles":["public"],"tablename":"pa_clients","permissive":"PERMISSIVE","policyname":"Users view tenant PA clients","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (pa_clients.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_clients","permissive":"PERMISSIVE","policyname":"tenant_users_delete_pa_clients","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"pa_clients","permissive":"PERMISSIVE","policyname":"tenant_users_insert_pa_clients","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (pa_clients.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (pa_clients.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_clients","permissive":"PERMISSIVE","policyname":"tenant_users_update_pa_clients","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (pa_clients.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (pa_clients.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_clients","permissive":"PERMISSIVE","policyname":"tenant_users_view_pa_clients","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"pa_clients_client_id_key","definition":"UNIQUE (client_id)"},{"name":"pa_clients_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pa_engagements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'Not Sent'::text","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"declined_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"cancelled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pa_fee_pct","type":"numeric(5,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"engagement_effective_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"scope_of_representation","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_document_file_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_document_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rendered_lor_html","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rendered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"rendered_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"signature_provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_envelope_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"envelope_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_provider_event_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pending_agreement_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_pa_engagements_claim","definition":"CREATE INDEX idx_pa_engagements_claim ON public.pa_engagements USING btree (claim_id)"},{"name":"idx_pa_engagements_contact","definition":"CREATE INDEX idx_pa_engagements_contact ON public.pa_engagements USING btree (contact_id)"},{"name":"idx_pa_engagements_external_envelope","definition":"CREATE INDEX idx_pa_engagements_external_envelope ON public.pa_engagements USING btree (signature_provider, external_envelope_id) WHERE (external_envelope_id IS NOT NULL)"},{"name":"idx_pa_engagements_pending_agreement_id","definition":"CREATE INDEX idx_pa_engagements_pending_agreement_id ON public.pa_engagements USING btree (pending_agreement_id) WHERE (pending_agreement_id IS NOT NULL)"},{"name":"idx_pa_engagements_status","definition":"CREATE INDEX idx_pa_engagements_status ON public.pa_engagements USING btree (tenant_org_id, status)"},{"name":"idx_pa_engagements_template","definition":"CREATE INDEX idx_pa_engagements_template ON public.pa_engagements USING btree (template_id)"},{"name":"idx_pa_engagements_tenant","definition":"CREATE INDEX idx_pa_engagements_tenant ON public.pa_engagements USING btree (tenant_org_id)"},{"name":"idx_pa_engagements_tenant_pending_agreement","definition":"CREATE INDEX idx_pa_engagements_tenant_pending_agreement ON public.pa_engagements USING btree (tenant_org_id, pending_agreement_id) WHERE (pending_agreement_id IS NOT NULL)"},{"name":"pa_engagements_pkey","definition":"CREATE UNIQUE INDEX pa_engagements_pkey ON public.pa_engagements USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_engagements","permissive":"PERMISSIVE","policyname":"pa_engagements_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"pa_engagements","permissive":"PERMISSIVE","policyname":"pa_engagements_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_engagements","permissive":"PERMISSIVE","policyname":"pa_engagements_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_engagements","permissive":"PERMISSIVE","policyname":"pa_engagements_update","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_pa_engagements_updated_at","definition":"CREATE TRIGGER trg_pa_engagements_updated_at BEFORE UPDATE ON pa_engagements FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"pa_engagements_pkey","definition":"PRIMARY KEY (id)"},{"name":"pa_engagements_status_check","definition":"CHECK (status = ANY (ARRAY['Not Sent'::text, 'Sent'::text, 'Viewed'::text, 'Signed'::text, 'Declined'::text, 'Cancelled'::text]))"}]},{"table":"pa_lor_envelope_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"engagement_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_envelope_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"received_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"processed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"processing_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pa_lor_env_events_engagement","definition":"CREATE INDEX idx_pa_lor_env_events_engagement ON public.pa_lor_envelope_events USING btree (engagement_id)"},{"name":"idx_pa_lor_env_events_external","definition":"CREATE INDEX idx_pa_lor_env_events_external ON public.pa_lor_envelope_events USING btree (provider, external_envelope_id)"},{"name":"idx_pa_lor_env_events_tenant","definition":"CREATE INDEX idx_pa_lor_env_events_tenant ON public.pa_lor_envelope_events USING btree (tenant_org_id)"},{"name":"pa_lor_envelope_events_pkey","definition":"CREATE UNIQUE INDEX pa_lor_envelope_events_pkey ON public.pa_lor_envelope_events USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_lor_envelope_events","permissive":"PERMISSIVE","policyname":"pa_lor_env_events_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"pa_lor_envelope_events","permissive":"PERMISSIVE","policyname":"pa_lor_env_events_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_lor_envelope_events","permissive":"PERMISSIVE","policyname":"pa_lor_env_events_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_lor_envelope_events","permissive":"PERMISSIVE","policyname":"pa_lor_env_events_update","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"pa_lor_envelope_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pa_lor_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"body_html","type":"text","default":"''::text","identity":"","not_null":true,"generated":""},{"name":"default_fee_percentage","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pa_lor_templates_active","definition":"CREATE INDEX idx_pa_lor_templates_active ON public.pa_lor_templates USING btree (tenant_org_id, is_active)"},{"name":"idx_pa_lor_templates_tenant","definition":"CREATE INDEX idx_pa_lor_templates_tenant ON public.pa_lor_templates USING btree (tenant_org_id)"},{"name":"pa_lor_templates_pkey","definition":"CREATE UNIQUE INDEX pa_lor_templates_pkey ON public.pa_lor_templates USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_lor_templates","permissive":"PERMISSIVE","policyname":"pa_lor_templates_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"pa_lor_templates","permissive":"PERMISSIVE","policyname":"pa_lor_templates_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_lor_templates","permissive":"PERMISSIVE","policyname":"pa_lor_templates_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pa_lor_templates","permissive":"PERMISSIVE","policyname":"pa_lor_templates_update","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_pa_lor_templates_single_default","definition":"CREATE TRIGGER trg_pa_lor_templates_single_default AFTER INSERT OR UPDATE OF is_default ON pa_lor_templates FOR EACH ROW EXECUTE FUNCTION pa_lor_templates_enforce_single_default()"},{"name":"trg_pa_lor_templates_touch","definition":"CREATE TRIGGER trg_pa_lor_templates_touch BEFORE UPDATE ON pa_lor_templates FOR EACH ROW EXECUTE FUNCTION pa_lor_templates_touch()"}],"constraints":[{"name":"pa_lor_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pa_staff_compliance","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"operational_role","type":"text","default":"'Public Adjuster'::text","identity":"","not_null":true,"generated":""},{"name":"license_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"licensed_states","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"license_expires_on","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"bond_expires_on","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"ce_due_on","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pa_staff_compliance_tenant","definition":"CREATE INDEX idx_pa_staff_compliance_tenant ON public.pa_staff_compliance USING btree (tenant_id)"},{"name":"idx_pa_staff_compliance_user","definition":"CREATE INDEX idx_pa_staff_compliance_user ON public.pa_staff_compliance USING btree (user_id)"},{"name":"pa_staff_compliance_pkey","definition":"CREATE UNIQUE INDEX pa_staff_compliance_pkey ON public.pa_staff_compliance USING btree (id)"},{"name":"pa_staff_compliance_tenant_id_user_id_key","definition":"CREATE UNIQUE INDEX pa_staff_compliance_tenant_id_user_id_key ON public.pa_staff_compliance USING btree (tenant_id, user_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"pa_staff_compliance","permissive":"PERMISSIVE","policyname":"PA staff compliance manager insert","schemaname":"public","with_check":"(has_role(uid(), tenant_id, 'Manager'::app_role) OR has_role(uid(), tenant_id, 'Owner'::app_role) OR has_role(uid(), tenant_id, 'Tenant Owner'::app_role) OR has_role(uid(), tenant_id, 'Admin'::app_role) OR has_role(uid(), tenant_id, 'GodMode'::app_role) OR has_role(uid(), tenant_id, 'PlatformAdmin'::app_role))"},{"cmd":"UPDATE","qual":"(has_role(uid(), tenant_id, 'Manager'::app_role) OR has_role(uid(), tenant_id, 'Owner'::app_role) OR has_role(uid(), tenant_id, 'Tenant Owner'::app_role) OR has_role(uid(), tenant_id, 'Admin'::app_role) OR has_role(uid(), tenant_id, 'GodMode'::app_role) OR has_role(uid(), tenant_id, 'PlatformAdmin'::app_role))","roles":["authenticated"],"tablename":"pa_staff_compliance","permissive":"PERMISSIVE","policyname":"PA staff compliance manager update","schemaname":"public","with_check":"(has_role(uid(), tenant_id, 'Manager'::app_role) OR has_role(uid(), tenant_id, 'Owner'::app_role) OR has_role(uid(), tenant_id, 'Tenant Owner'::app_role) OR has_role(uid(), tenant_id, 'Admin'::app_role) OR has_role(uid(), tenant_id, 'GodMode'::app_role) OR has_role(uid(), tenant_id, 'PlatformAdmin'::app_role))"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["public"],"tablename":"pa_staff_compliance","permissive":"PERMISSIVE","policyname":"PA staff compliance tenant read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"pa_staff_compliance_pkey","definition":"PRIMARY KEY (id)"},{"name":"pa_staff_compliance_tenant_id_user_id_key","definition":"UNIQUE (tenant_id, user_id)"}]},{"table":"page_views","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"page_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"page_title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"entered_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"exited_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_page_views_tenant","definition":"CREATE INDEX idx_page_views_tenant ON public.page_views USING btree (tenant_id, entered_at DESC)"},{"name":"idx_page_views_user","definition":"CREATE INDEX idx_page_views_user ON public.page_views USING btree (user_id, entered_at DESC)"},{"name":"idx_page_views_user_tenant_path_entered_at","definition":"CREATE INDEX idx_page_views_user_tenant_path_entered_at ON public.page_views USING btree (user_id, COALESCE(tenant_id, ''::text), page_path, entered_at DESC)"},{"name":"page_views_pkey","definition":"CREATE UNIQUE INDEX page_views_pkey ON public.page_views USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"page_views","permissive":"PERMISSIVE","policyname":"Users can insert own page views","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"page_views","permissive":"PERMISSIVE","policyname":"Users can update own page views","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((uid() = user_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"page_views","permissive":"PERMISSIVE","policyname":"Users can view own page views","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_dedupe_page_view_insert","definition":"CREATE TRIGGER trg_dedupe_page_view_insert BEFORE INSERT ON page_views FOR EACH ROW EXECUTE FUNCTION dedupe_page_view_insert()"}],"constraints":[{"name":"page_views_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"parcel_datasets","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"drive_file_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage","type":"dataset_stage","default":"'raw'::dataset_stage","identity":"","not_null":true,"generated":""},{"name":"uploaded_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"imported_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_parcel_datasets_created_at","definition":"CREATE INDEX idx_parcel_datasets_created_at ON public.parcel_datasets USING btree (created_at DESC)"},{"name":"idx_parcel_datasets_jurisdiction","definition":"CREATE INDEX idx_parcel_datasets_jurisdiction ON public.parcel_datasets USING btree (jurisdiction_id)"},{"name":"idx_parcel_datasets_stage","definition":"CREATE INDEX idx_parcel_datasets_stage ON public.parcel_datasets USING btree (stage)"},{"name":"idx_parcel_datasets_uploaded_by","definition":"CREATE INDEX idx_parcel_datasets_uploaded_by ON public.parcel_datasets USING btree (uploaded_by)"},{"name":"parcel_datasets_pkey","definition":"CREATE UNIQUE INDEX parcel_datasets_pkey ON public.parcel_datasets USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"parcel_datasets","permissive":"PERMISSIVE","policyname":"Users can view parcel datasets","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"parcel_datasets","permissive":"PERMISSIVE","policyname":"platform_admin_manage_parcel_datasets","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"parcel_datasets_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pcg_growth_tasks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"opportunity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"task_type","type":"text","default":"'follow_up'::text","identity":"","not_null":true,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'open'::text","identity":"","not_null":true,"generated":""},{"name":"summary","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"draft_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_required","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"is_demo","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pcg_growth_tasks_opportunity","definition":"CREATE INDEX idx_pcg_growth_tasks_opportunity ON public.pcg_growth_tasks USING btree (opportunity_id)"},{"name":"idx_pcg_growth_tasks_tenant_status_due","definition":"CREATE INDEX idx_pcg_growth_tasks_tenant_status_due ON public.pcg_growth_tasks USING btree (tenant_id, status, due_at)"},{"name":"pcg_growth_tasks_pkey","definition":"CREATE UNIQUE INDEX pcg_growth_tasks_pkey ON public.pcg_growth_tasks USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"pcg_growth_tasks","permissive":"PERMISSIVE","policyname":"pcg_growth_tasks_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"pcg_growth_tasks","permissive":"PERMISSIVE","policyname":"pcg_growth_tasks_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"pcg_growth_tasks","permissive":"PERMISSIVE","policyname":"pcg_growth_tasks_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"pcg_growth_tasks","permissive":"PERMISSIVE","policyname":"pcg_growth_tasks_update","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_id) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"pcg_growth_tasks_opportunity_id_fkey","definition":"FOREIGN KEY (opportunity_id) REFERENCES opportunity_radar_opportunities(id) ON DELETE CASCADE"},{"name":"pcg_growth_tasks_pkey","definition":"PRIMARY KEY (id)"},{"name":"pcg_growth_tasks_status_check","definition":"CHECK (status = ANY (ARRAY['open'::text, 'completed'::text, 'dismissed'::text]))"},{"name":"pcg_growth_tasks_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"pending_agreements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"recipient_email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"recipient_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"agreement_html","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"agreement_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variables","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"sign_token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"custom_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_by","type":"text","default":"'System'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sent_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_fields","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"completed_fields","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_pdf_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_pdf_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_pdf_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_pdf_generated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_pending_agreements_status","definition":"CREATE INDEX idx_pending_agreements_status ON public.pending_agreements USING btree (status)"},{"name":"idx_pending_agreements_token","definition":"CREATE INDEX idx_pending_agreements_token ON public.pending_agreements USING btree (sign_token)"},{"name":"pending_agreements_event_booking_idx","definition":"CREATE INDEX pending_agreements_event_booking_idx ON public.pending_agreements USING btree (event_booking_id)"},{"name":"pending_agreements_pkey","definition":"CREATE UNIQUE INDEX pending_agreements_pkey ON public.pending_agreements USING btree (id)"},{"name":"pending_agreements_sign_token_key","definition":"CREATE UNIQUE INDEX pending_agreements_sign_token_key ON public.pending_agreements USING btree (sign_token)"}],"policies":[{"cmd":"SELECT","qual":"(is_tenant_member((tenant_id)::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"pending_agreements","permissive":"PERMISSIVE","policyname":"Tenant members can read pending agreements","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_tenant_member((tenant_id)::text)","roles":["authenticated"],"tablename":"pending_agreements","permissive":"PERMISSIVE","policyname":"tenant_members_manage_agreements","schemaname":"public","with_check":"is_tenant_member((tenant_id)::text)"}],"triggers":[{"name":"trg_auto_send_portal_welcome","definition":"CREATE TRIGGER trg_auto_send_portal_welcome AFTER UPDATE OF signed_at ON pending_agreements FOR EACH ROW EXECUTE FUNCTION auto_send_portal_welcome_on_signed_agreement()"},{"name":"trg_enforce_pa_rights_before_lor","definition":"CREATE TRIGGER trg_enforce_pa_rights_before_lor BEFORE INSERT ON pending_agreements FOR EACH ROW EXECUTE FUNCTION enforce_pa_rights_before_lor()"},{"name":"trg_sync_321_lockout_signed_agreement","definition":"CREATE TRIGGER trg_sync_321_lockout_signed_agreement AFTER UPDATE OF status, signer_name, signed_at ON pending_agreements FOR EACH ROW EXECUTE FUNCTION sync_321_lockout_signed_agreement()"},{"name":"trg_sync_pa_engagement_from_pending_agreement","definition":"CREATE TRIGGER trg_sync_pa_engagement_from_pending_agreement AFTER UPDATE OF status ON pending_agreements FOR EACH ROW EXECUTE FUNCTION tg_sync_pa_engagement_from_pending_agreement()"}],"constraints":[{"name":"pending_agreements_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"pending_agreements_pkey","definition":"PRIMARY KEY (id)"},{"name":"pending_agreements_sign_token_key","definition":"UNIQUE (sign_token)"}]},{"table":"pending_join_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"pending_signup_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"requested_by_email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"requested_by_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"owner_notified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_response_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_response_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"denial_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"token_expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pending_join_tenant","definition":"CREATE INDEX idx_pending_join_tenant ON public.pending_join_requests USING btree (tenant_id, status)"},{"name":"idx_pending_join_token","definition":"CREATE INDEX idx_pending_join_token ON public.pending_join_requests USING btree (approval_token) WHERE (approval_token IS NOT NULL)"},{"name":"idx_pending_join_unique","definition":"CREATE UNIQUE INDEX idx_pending_join_unique ON public.pending_join_requests USING btree (pending_signup_id, tenant_id)"},{"name":"pending_join_requests_approval_token_key","definition":"CREATE UNIQUE INDEX pending_join_requests_approval_token_key ON public.pending_join_requests USING btree (approval_token)"},{"name":"pending_join_requests_pkey","definition":"CREATE UNIQUE INDEX pending_join_requests_pkey ON public.pending_join_requests USING btree (id)"}],"policies":[{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships utm\n     JOIN user_roles ur ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((utm.tenant_id = pending_join_requests.tenant_id) AND (utm.user_id = uid()) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["public"],"tablename":"pending_join_requests","permissive":"PERMISSIVE","policyname":"Owners can update join requests for their tenants","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships utm\n     JOIN user_roles ur ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((utm.tenant_id = pending_join_requests.tenant_id) AND (utm.user_id = uid()) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["public"],"tablename":"pending_join_requests","permissive":"PERMISSIVE","policyname":"Owners can view join requests for their tenants","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((jwt() ->> 'role'::text) = 'service_role'::text)","roles":["public"],"tablename":"pending_join_requests","permissive":"PERMISSIVE","policyname":"Service role full access to join requests","schemaname":"public","with_check":null}],"triggers":[{"name":"update_pending_join_requests_updated_at","definition":"CREATE TRIGGER update_pending_join_requests_updated_at BEFORE UPDATE ON pending_join_requests FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"pending_join_requests_approval_token_key","definition":"UNIQUE (approval_token)"},{"name":"pending_join_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"pending_join_requests_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'approved_by_owner'::text, 'denied_by_owner'::text]))"}]},{"table":"pending_signups","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"full_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"company_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"company_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"pin_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"license_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending_agreement'::text","identity":"","not_null":true,"generated":""},{"name":"signup_token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"agreement_html","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_version","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":"(now() + '7 days'::interval)","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"company_slug","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_signed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_json","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenancy","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"joining_existing","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"target_tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_pending_signups_email","definition":"CREATE INDEX idx_pending_signups_email ON public.pending_signups USING btree (email)"},{"name":"idx_pending_signups_expires_at","definition":"CREATE INDEX idx_pending_signups_expires_at ON public.pending_signups USING btree (expires_at)"},{"name":"idx_pending_signups_status","definition":"CREATE INDEX idx_pending_signups_status ON public.pending_signups USING btree (status)"},{"name":"idx_pending_signups_token","definition":"CREATE INDEX idx_pending_signups_token ON public.pending_signups USING btree (signup_token)"},{"name":"pending_signups_email_key","definition":"CREATE UNIQUE INDEX pending_signups_email_key ON public.pending_signups USING btree (email)"},{"name":"pending_signups_pkey","definition":"CREATE UNIQUE INDEX pending_signups_pkey ON public.pending_signups USING btree (id)"},{"name":"pending_signups_signup_token_key","definition":"CREATE UNIQUE INDEX pending_signups_signup_token_key ON public.pending_signups USING btree (signup_token)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"pending_signups","permissive":"PERMISSIVE","policyname":"Authenticated users can create pending signups","schemaname":"public","with_check":"((current_setting('role'::text) = 'service_role'::text) OR (uid() IS NOT NULL))"},{"cmd":"SELECT","qual":"(email = (jwt() ->> 'email'::text))","roles":["authenticated"],"tablename":"pending_signups","permissive":"PERMISSIVE","policyname":"Users can view own pending signup","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin()","roles":["public"],"tablename":"pending_signups","permissive":"PERMISSIVE","policyname":"pending_signups_admin","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"pending_signups","permissive":"PERMISSIVE","policyname":"platform_admin_manage_pending_signups","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"pending_signups_email_key","definition":"UNIQUE (email)"},{"name":"pending_signups_pkey","definition":"PRIMARY KEY (id)"},{"name":"pending_signups_signup_token_key","definition":"UNIQUE (signup_token)"}]},{"table":"pending_voicemail_drops","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parent_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"homeowner_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"scheduled_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"fire_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'armed'::text","identity":"","not_null":true,"generated":""},{"name":"trigger_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"cancellation_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"fired_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"slot_requested","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_release_requested","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"rep_released_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"timing_mode","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"playback_started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"failed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"inject_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"drop_requested_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"parking_started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"parking_timeout_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"parking_twilio_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parking_timeout_hangup","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"parking_failed_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"inject_started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"slot_selection_mode","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"slot_resolved","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempt_basis","type":"integer","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"pending_voicemail_drops_armed_homeowner_unique","definition":"CREATE UNIQUE INDEX pending_voicemail_drops_armed_homeowner_unique ON public.pending_voicemail_drops USING btree (homeowner_call_sid) WHERE ((status = ANY (ARRAY['armed'::text, 'queued_waiting_for_homeowner_leg'::text, 'playback_started'::text])) AND (homeowner_call_sid IS NOT NULL))"},{"name":"pending_voicemail_drops_armed_session_unique","definition":"CREATE UNIQUE INDEX pending_voicemail_drops_armed_session_unique ON public.pending_voicemail_drops USING btree (active_call_session_id) WHERE ((status = ANY (ARRAY['armed'::text, 'queued_waiting_for_homeowner_leg'::text, 'playback_started'::text])) AND (active_call_session_id IS NOT NULL))"},{"name":"pending_voicemail_drops_fire_at_idx","definition":"CREATE INDEX pending_voicemail_drops_fire_at_idx ON public.pending_voicemail_drops USING btree (fire_at) WHERE (status = 'armed'::text)"},{"name":"pending_voicemail_drops_pkey","definition":"CREATE UNIQUE INDEX pending_voicemail_drops_pkey ON public.pending_voicemail_drops USING btree (id)"},{"name":"pending_voicemail_drops_session_idx","definition":"CREATE INDEX pending_voicemail_drops_session_idx ON public.pending_voicemail_drops USING btree (active_call_session_id)"},{"name":"pending_voicemail_drops_tenant_idx","definition":"CREATE INDEX pending_voicemail_drops_tenant_idx ON public.pending_voicemail_drops USING btree (tenant_id, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"pending_voicemail_drops","permissive":"PERMISSIVE","policyname":"tenant members read pending voicemail drops","schemaname":"public","with_check":null}],"triggers":[{"name":"pending_voicemail_drops_touch","definition":"CREATE TRIGGER pending_voicemail_drops_touch BEFORE UPDATE ON pending_voicemail_drops FOR EACH ROW EXECUTE FUNCTION tg_pending_voicemail_drops_touch()"}],"constraints":[{"name":"pending_voicemail_drops_pkey","definition":"PRIMARY KEY (id)"},{"name":"pending_voicemail_drops_status_check","definition":"CHECK (status = ANY (ARRAY['armed'::text, 'queued_waiting_for_homeowner_leg'::text, 'playback_started'::text, 'cancelled'::text, 'fired'::text, 'fired_manual'::text, 'failed'::text]))"}]},{"table":"performance_benchmarks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"metric_name","type":"character varying(100)","default":null,"identity":"","not_null":true,"generated":""},{"name":"benchmark_type","type":"character varying(50)","default":null,"identity":"","not_null":true,"generated":""},{"name":"benchmark_value","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_type","type":"character varying(20)","default":null,"identity":"","not_null":true,"generated":""},{"name":"valid_from","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"valid_until","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"performance_benchmarks_pkey","definition":"CREATE UNIQUE INDEX performance_benchmarks_pkey ON public.performance_benchmarks USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"performance_benchmarks","permissive":"PERMISSIVE","policyname":"Users can view benchmarks","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"performance_benchmarks_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"permissions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"permission_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"permissions_permission_key_key","definition":"CREATE UNIQUE INDEX permissions_permission_key_key ON public.permissions USING btree (permission_key)"},{"name":"permissions_pkey","definition":"CREATE UNIQUE INDEX permissions_pkey ON public.permissions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"permissions","permissive":"PERMISSIVE","policyname":"Permissions viewable by authenticated users","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"permissions_permission_key_key","definition":"UNIQUE (permission_key)"},{"name":"permissions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"permit_lookup_attempts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"full_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"searched_jurisdiction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"search_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"search_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"result_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"permits_found_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"roof_permits_found_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"failure_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_response","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"triggered_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_permit_lookup_attempts_tenantless_unknown_recent","definition":"CREATE INDEX idx_permit_lookup_attempts_tenantless_unknown_recent ON public.permit_lookup_attempts USING btree (created_at DESC) WHERE ((tenant_org_id IS NULL) AND (COALESCE(NULLIF(btrim(searched_source), ''::text), 'Unknown'::text) = 'Unknown'::text) AND (COALESCE(NULLIF(btrim(searched_jurisdiction), ''::text), 'Unknown'::text) = 'Unknown'::text) AND (COALESCE(NULLIF(btrim(search_method), ''::text), 'address'::text) = 'address'::text) AND (result_status = 'source_unavailable'::text))"},{"name":"permit_lookup_attempts_full_address_created_at_idx","definition":"CREATE INDEX permit_lookup_attempts_full_address_created_at_idx ON public.permit_lookup_attempts USING btree (full_address, created_at DESC)"},{"name":"permit_lookup_attempts_pkey","definition":"CREATE UNIQUE INDEX permit_lookup_attempts_pkey ON public.permit_lookup_attempts USING btree (id)"},{"name":"permit_lookup_attempts_tenant_idx","definition":"CREATE INDEX permit_lookup_attempts_tenant_idx ON public.permit_lookup_attempts USING btree (tenant_org_id, created_at DESC)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"permit_lookup_attempts","permissive":"PERMISSIVE","policyname":"lookup insert tenant","schemaname":"public","with_check":"((tenant_org_id IS NULL) OR (tenant_org_id = ANY (COALESCE(( SELECT current_user_tenant_ids() AS current_user_tenant_ids), ARRAY[]::uuid[]))) OR ( SELECT is_system_admin(uid()) AS is_system_admin))"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR (tenant_org_id = ANY (COALESCE(( SELECT current_user_tenant_ids() AS current_user_tenant_ids), ARRAY[]::uuid[]))) OR ( SELECT is_system_admin(uid()) AS is_system_admin))","roles":["authenticated"],"tablename":"permit_lookup_attempts","permissive":"PERMISSIVE","policyname":"lookup read tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_fill_permit_lookup_attempt_attribution","definition":"CREATE TRIGGER trg_fill_permit_lookup_attempt_attribution BEFORE INSERT ON permit_lookup_attempts FOR EACH ROW EXECUTE FUNCTION fill_permit_lookup_attempt_attribution()"}],"constraints":[{"name":"permit_lookup_attempts_no_tenantless_unknown_source","definition":"CHECK (tenant_org_id IS NOT NULL OR NOT (COALESCE(NULLIF(btrim(searched_source), ''::text), 'Unknown'::text) = 'Unknown'::text AND COALESCE(NULLIF(btrim(searched_jurisdiction), ''::text), 'Unknown'::text) = 'Unknown'::text AND COALESCE(NULLIF(btrim(search_method), ''::text), 'address'::text) = 'address'::text AND result_status = 'source_unavailable'::text)) NOT VALID"},{"name":"permit_lookup_attempts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"permit_source_configs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"municipality","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"county","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_type","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""},{"name":"base_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"api_endpoint_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_office_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"enabled","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"requires_auth","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"public_api_available","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_psc_enabled","definition":"CREATE INDEX idx_psc_enabled ON public.permit_source_configs USING btree (enabled)"},{"name":"idx_psc_location","definition":"CREATE INDEX idx_psc_location ON public.permit_source_configs USING btree (state, municipality)"},{"name":"idx_psc_tenant","definition":"CREATE INDEX idx_psc_tenant ON public.permit_source_configs USING btree (tenant_org_id)"},{"name":"permit_source_configs_pkey","definition":"CREATE UNIQUE INDEX permit_source_configs_pkey ON public.permit_source_configs USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_global_admin(uid())","roles":["authenticated"],"tablename":"permit_source_configs","permissive":"PERMISSIVE","policyname":"psc_delete_admins","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"permit_source_configs","permissive":"PERMISSIVE","policyname":"psc_insert_admins","schemaname":"public","with_check":"(is_global_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_admin_or_higher(uid(), tenant_org_id)))"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(uid(), tenant_org_id))","roles":["authenticated"],"tablename":"permit_source_configs","permissive":"PERMISSIVE","policyname":"psc_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_global_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_admin_or_higher(uid(), tenant_org_id)))","roles":["authenticated"],"tablename":"permit_source_configs","permissive":"PERMISSIVE","policyname":"psc_update_admins","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_psc_updated_at","definition":"CREATE TRIGGER trg_psc_updated_at BEFORE UPDATE ON permit_source_configs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"permit_source_configs_pkey","definition":"PRIMARY KEY (id)"},{"name":"permit_source_configs_source_type_check","definition":"CHECK (source_type = ANY (ARRAY['manual'::text, 'website'::text, 'csv_upload'::text, 'arcgis'::text, 'ckan'::text, 'api'::text, 'scraper'::text, 'foil'::text]))"}]},{"table":"permit_sources","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"county","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":"'FL'::text","identity":"","not_null":true,"generated":""},{"name":"source_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"portal_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"portal_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"search_methods_supported","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"requires_login","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"permit_sources_pkey","definition":"CREATE UNIQUE INDEX permit_sources_pkey ON public.permit_sources USING btree (id)"},{"name":"permit_sources_unique","definition":"CREATE UNIQUE INDEX permit_sources_unique ON public.permit_sources USING btree (jurisdiction_name, source_type)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin()","roles":["authenticated"],"tablename":"permit_sources","permissive":"PERMISSIVE","policyname":"permit_sources admin write","schemaname":"public","with_check":"is_system_admin()"},{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"permit_sources","permissive":"PERMISSIVE","policyname":"permit_sources read auth","schemaname":"public","with_check":null}],"triggers":[{"name":"permit_sources_updated_at","definition":"CREATE TRIGGER permit_sources_updated_at BEFORE UPDATE ON permit_sources FOR EACH ROW EXECUTE FUNCTION set_updated_at_simple()"}],"constraints":[{"name":"permit_sources_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"permits","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"permit_source","default":"'MANUAL'::permit_source","identity":"","not_null":true,"generated":""},{"name":"jurisdiction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"municipality","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"county","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"permit_status","default":"'unknown'::permit_status","identity":"","not_null":true,"generated":""},{"name":"permit_required","type":"permit_required_state","default":"'unknown'::permit_required_state","identity":"","not_null":true,"generated":""},{"name":"applied_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"issued_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"final_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"applicant","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"valuation","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"square_feet","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"document_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_checked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"checked_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_roof_related","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_permits_contact","definition":"CREATE INDEX idx_permits_contact ON public.permits USING btree (contact_id) WHERE (contact_id IS NOT NULL)"},{"name":"idx_permits_lead","definition":"CREATE INDEX idx_permits_lead ON public.permits USING btree (lead_id) WHERE (lead_id IS NOT NULL)"},{"name":"idx_permits_property","definition":"CREATE INDEX idx_permits_property ON public.permits USING btree (property_id) WHERE (property_id IS NOT NULL)"},{"name":"idx_permits_roof","definition":"CREATE INDEX idx_permits_roof ON public.permits USING btree (tenant_org_id, is_roof_related) WHERE (is_roof_related = true)"},{"name":"idx_permits_source","definition":"CREATE INDEX idx_permits_source ON public.permits USING btree (source)"},{"name":"idx_permits_tenant","definition":"CREATE INDEX idx_permits_tenant ON public.permits USING btree (tenant_org_id)"},{"name":"permits_pkey","definition":"CREATE UNIQUE INDEX permits_pkey ON public.permits USING btree (id)"},{"name":"uq_permits_tenant_source_number","definition":"CREATE UNIQUE INDEX uq_permits_tenant_source_number ON public.permits USING btree (tenant_org_id, source, permit_number) WHERE (permit_number IS NOT NULL)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member((tenant_org_id)::text)","roles":["authenticated"],"tablename":"permits","permissive":"PERMISSIVE","policyname":"permits_delete_tenant_members","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"permits","permissive":"PERMISSIVE","policyname":"permits_insert_tenant_members","schemaname":"public","with_check":"(is_tenant_member((tenant_org_id)::text) AND ((created_by IS NULL) OR (created_by = uid())))"},{"cmd":"SELECT","qual":"is_tenant_member((tenant_org_id)::text)","roles":["authenticated"],"tablename":"permits","permissive":"PERMISSIVE","policyname":"permits_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member((tenant_org_id)::text)","roles":["authenticated"],"tablename":"permits","permissive":"PERMISSIVE","policyname":"permits_update_tenant_members","schemaname":"public","with_check":"is_tenant_member((tenant_org_id)::text)"}],"triggers":[{"name":"trg_permits_flag_roof","definition":"CREATE TRIGGER trg_permits_flag_roof BEFORE INSERT OR UPDATE OF permit_type, description, notes ON permits FOR EACH ROW EXECUTE FUNCTION flag_roof_related_permit()"},{"name":"trg_permits_updated_at","definition":"CREATE TRIGGER trg_permits_updated_at BEFORE UPDATE ON permits FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"permits_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pin_reset_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"reset_token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"request_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"requested_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":"(now() + '24:00:00'::interval)","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"pin_reset_requests_pkey","definition":"CREATE UNIQUE INDEX pin_reset_requests_pkey ON public.pin_reset_requests USING btree (id)"},{"name":"pin_reset_requests_request_id_key","definition":"CREATE UNIQUE INDEX pin_reset_requests_request_id_key ON public.pin_reset_requests USING btree (request_id)"},{"name":"pin_reset_requests_reset_token_key","definition":"CREATE UNIQUE INDEX pin_reset_requests_reset_token_key ON public.pin_reset_requests USING btree (reset_token)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"pin_reset_requests","permissive":"PERMISSIVE","policyname":"platform_admin_manage_pin_resets","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"pin_reset_requests","permissive":"PERMISSIVE","policyname":"users_insert_own_pin_reset","schemaname":"public","with_check":"((email = (jwt() ->> 'email'::text)) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"pin_reset_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"pin_reset_requests_request_id_key","definition":"UNIQUE (request_id)"},{"name":"pin_reset_requests_reset_token_key","definition":"UNIQUE (reset_token)"}]},{"table":"pipeline_automation_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"rule_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"trigger_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"actions_executed","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"success","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"execution_time_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_pipeline_automation_log_contact","definition":"CREATE INDEX idx_pipeline_automation_log_contact ON public.pipeline_automation_log USING btree (contact_id)"},{"name":"idx_pipeline_automation_log_rule","definition":"CREATE INDEX idx_pipeline_automation_log_rule ON public.pipeline_automation_log USING btree (rule_id)"},{"name":"pipeline_automation_log_pkey","definition":"CREATE UNIQUE INDEX pipeline_automation_log_pkey ON public.pipeline_automation_log USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"pipeline_automation_log","permissive":"PERMISSIVE","policyname":"Tenant isolation for pipeline_automation_log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"pipeline_automation_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pipeline_automation_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"trigger_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"conditions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"actions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"priority","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"execution_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"derived_from_template_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adopted_admin_version","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_par_derived_template_key","definition":"CREATE INDEX idx_par_derived_template_key ON public.pipeline_automation_rules USING btree (derived_from_template_key)"},{"name":"idx_pipeline_automation_rules_tenant","definition":"CREATE INDEX idx_pipeline_automation_rules_tenant ON public.pipeline_automation_rules USING btree (tenant_org_id)"},{"name":"pipeline_automation_rules_pkey","definition":"CREATE UNIQUE INDEX pipeline_automation_rules_pkey ON public.pipeline_automation_rules USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"pipeline_automation_rules","permissive":"PERMISSIVE","policyname":"Tenant isolation for pipeline_automation_rules","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"pipeline_automation_rules_pkey","definition":"PRIMARY KEY (id)"},{"name":"pipeline_automation_rules_trigger_type_check","definition":"CHECK (trigger_type = ANY (ARRAY['status_change'::text, 'stage_change'::text, 'field_update'::text, 'time_based'::text, 'score_threshold'::text, 'event_stage_change'::text, 'event_time'::text, 'event_updated'::text]))"}]},{"table":"pipeline_movement_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_stage","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_outcome","type":"call_outcome","default":null,"identity":"","not_null":false,"generated":""},{"name":"triggered_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_pipeline_audit_contact","definition":"CREATE INDEX idx_pipeline_audit_contact ON public.pipeline_movement_audit USING btree (contact_id)"},{"name":"idx_pipeline_audit_tenant","definition":"CREATE INDEX idx_pipeline_audit_tenant ON public.pipeline_movement_audit USING btree (tenant_org_id)"},{"name":"pipeline_movement_audit_pkey","definition":"CREATE UNIQUE INDEX pipeline_movement_audit_pkey ON public.pipeline_movement_audit USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = pipeline_movement_audit.tenant_org_id))))","roles":["public"],"tablename":"pipeline_movement_audit","permissive":"PERMISSIVE","policyname":"Users view tenant pipeline audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"pipeline_movement_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"pipeline_stages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"order_index","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"color","type":"text","default":"'gray'::text","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"is_closed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"is_won","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"pipeline_kind","type":"pipeline_kind","default":"'JOB'::pipeline_kind","identity":"","not_null":true,"generated":""},{"name":"tenancy_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_template","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"derived_from_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_using_master_template","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"template_stage_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adopted_admin_version","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_pipeline_stages_order","definition":"CREATE INDEX idx_pipeline_stages_order ON public.pipeline_stages USING btree (tenant_org_id, order_index)"},{"name":"idx_pipeline_stages_template","definition":"CREATE INDEX idx_pipeline_stages_template ON public.pipeline_stages USING btree (is_template, tenancy_type) WHERE (is_template = true)"},{"name":"idx_pipeline_stages_template_lookup","definition":"CREATE INDEX idx_pipeline_stages_template_lookup ON public.pipeline_stages USING btree (tenant_type, pipeline_kind, is_template) WHERE (is_template = true)"},{"name":"idx_pipeline_stages_templates","definition":"CREATE INDEX idx_pipeline_stages_templates ON public.pipeline_stages USING btree (tenancy_type, is_template) WHERE (tenant_org_id IS NULL)"},{"name":"idx_pipeline_stages_tenant","definition":"CREATE INDEX idx_pipeline_stages_tenant ON public.pipeline_stages USING btree (tenant_org_id)"},{"name":"idx_pipeline_stages_tenant_kind","definition":"CREATE INDEX idx_pipeline_stages_tenant_kind ON public.pipeline_stages USING btree (tenant_org_id, pipeline_kind, order_index) WHERE (tenant_org_id IS NOT NULL)"},{"name":"idx_pipeline_stages_tenant_order","definition":"CREATE INDEX idx_pipeline_stages_tenant_order ON public.pipeline_stages USING btree (tenant_org_id, order_index)"},{"name":"pipeline_stages_pkey","definition":"CREATE UNIQUE INDEX pipeline_stages_pkey ON public.pipeline_stages USING btree (id)"},{"name":"pipeline_stages_tenant_org_id_pipeline_kind_name_key","definition":"CREATE UNIQUE INDEX pipeline_stages_tenant_org_id_pipeline_kind_name_key ON public.pipeline_stages USING btree (tenant_org_id, pipeline_kind, name)"}],"policies":[{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND (is_system_admin(uid()) OR is_tenant_owner_for(uid(), tenant_org_id)))","roles":["public"],"tablename":"pipeline_stages","permissive":"PERMISSIVE","policyname":"Tenant owners manage tenant stages","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = pipeline_stages.tenant_org_id))))","roles":["authenticated"],"tablename":"pipeline_stages","permissive":"PERMISSIVE","policyname":"Users can view stages in their tenant","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(((tenant_org_id IS NULL) AND (is_template = true)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = pipeline_stages.tenant_org_id)))))","roles":["public"],"tablename":"pipeline_stages","permissive":"PERMISSIVE","policyname":"Users view tenant stages and templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"pipeline_stages","permissive":"PERMISSIVE","policyname":"platform_admin_manage_pipeline_stages","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"update_pipeline_stages_updated_at","definition":"CREATE TRIGGER update_pipeline_stages_updated_at BEFORE UPDATE ON pipeline_stages FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"pipeline_stages_pkey","definition":"PRIMARY KEY (id)"},{"name":"pipeline_stages_tenant_org_id_pipeline_kind_name_key","definition":"UNIQUE (tenant_org_id, pipeline_kind, name)"}]},{"table":"pipeline_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"pipeline_kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"color","type":"text","default":"'blue'::text","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"is_closed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"is_won","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_pipeline_templates_tenant_type","definition":"CREATE INDEX idx_pipeline_templates_tenant_type ON public.pipeline_templates USING btree (tenant_type, pipeline_kind)"},{"name":"pipeline_templates_pkey","definition":"CREATE UNIQUE INDEX pipeline_templates_pkey ON public.pipeline_templates USING btree (id)"},{"name":"pipeline_templates_tenant_type_pipeline_kind_stage_key_key","definition":"CREATE UNIQUE INDEX pipeline_templates_tenant_type_pipeline_kind_stage_key_key ON public.pipeline_templates USING btree (tenant_type, pipeline_kind, stage_key)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"pipeline_templates","permissive":"PERMISSIVE","policyname":"Authenticated users can view pipeline templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"pipeline_templates","permissive":"PERMISSIVE","policyname":"platform_admin_manage_pipeline_templates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"pipeline_templates_pipeline_kind_check","definition":"CHECK (pipeline_kind = ANY (ARRAY['JOB'::text, 'CLAIM'::text]))"},{"name":"pipeline_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"pipeline_templates_tenant_type_check","definition":"CHECK (tenant_type = ANY (ARRAY['MITIGATION'::text, 'ROOFING_COMPANY'::text, 'PUBLIC_ADJUSTER_FIRM'::text, 'REALTOR'::text]))"},{"name":"pipeline_templates_tenant_type_pipeline_kind_stage_key_key","definition":"UNIQUE (tenant_type, pipeline_kind, stage_key)"}]},{"table":"pipeline_transition_rules","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_stage_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_stage_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_outcome","type":"call_outcome","default":null,"identity":"","not_null":true,"generated":""},{"name":"auto_advance","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_transition_rules_tenant","definition":"CREATE INDEX idx_transition_rules_tenant ON public.pipeline_transition_rules USING btree (tenant_org_id)"},{"name":"pipeline_transition_rules_pkey","definition":"CREATE UNIQUE INDEX pipeline_transition_rules_pkey ON public.pipeline_transition_rules USING btree (id)"},{"name":"pipeline_transition_rules_tenant_org_id_from_stage_id_trigg_key","definition":"CREATE UNIQUE INDEX pipeline_transition_rules_tenant_org_id_from_stage_id_trigg_key ON public.pipeline_transition_rules USING btree (tenant_org_id, from_stage_id, trigger_outcome)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = pipeline_transition_rules.tenant_org_id))))","roles":["public"],"tablename":"pipeline_transition_rules","permissive":"PERMISSIVE","policyname":"Users view tenant transition rules","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"pipeline_transition_rules","permissive":"PERMISSIVE","policyname":"platform_admin_manage_transition_rules","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"pipeline_transition_rules_pkey","definition":"PRIMARY KEY (id)"},{"name":"pipeline_transition_rules_tenant_org_id_from_stage_id_trigg_key","definition":"UNIQUE (tenant_org_id, from_stage_id, trigger_outcome)"}]},{"table":"plan_features","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"plan_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"feature_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"limit_value","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_boolean","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"plan_features_pkey","definition":"CREATE UNIQUE INDEX plan_features_pkey ON public.plan_features USING btree (id)"},{"name":"plan_features_plan_id_feature_key_key","definition":"CREATE UNIQUE INDEX plan_features_plan_id_feature_key_key ON public.plan_features USING btree (plan_id, feature_key)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"plan_features","permissive":"PERMISSIVE","policyname":"Only system admins modify plan features","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"true","roles":["public"],"tablename":"plan_features","permissive":"PERMISSIVE","policyname":"Plan features are publicly readable","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"plan_features_pkey","definition":"PRIMARY KEY (id)"},{"name":"plan_features_plan_id_feature_key_key","definition":"UNIQUE (plan_id, feature_key)"}]},{"table":"plans","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tier","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"monthly_cents","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"annual_cents","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"included_seats","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"additional_seat_cents","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"vertical_default","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_public","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"stripe_price_id_monthly","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"stripe_price_id_yearly","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"plans_pkey","definition":"CREATE UNIQUE INDEX plans_pkey ON public.plans USING btree (id)"},{"name":"plans_slug_key","definition":"CREATE UNIQUE INDEX plans_slug_key ON public.plans USING btree (slug)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"plans","permissive":"PERMISSIVE","policyname":"Only system admins modify plans","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((is_public = true) OR is_system_admin(uid()))","roles":["public"],"tablename":"plans","permissive":"PERMISSIVE","policyname":"Plans are publicly readable","schemaname":"public","with_check":null}],"triggers":[{"name":"update_plans_updated_at","definition":"CREATE TRIGGER update_plans_updated_at BEFORE UPDATE ON plans FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"plans_pkey","definition":"PRIMARY KEY (id)"},{"name":"plans_slug_key","definition":"UNIQUE (slug)"},{"name":"plans_tier_check","definition":"CHECK (tier = ANY (ARRAY['trial'::text, 'starter'::text, 'pro'::text, 'brokerage'::text, 'enterprise'::text]))"}]},{"table":"platform_changelog","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'improvement'::text","identity":"","not_null":true,"generated":""},{"name":"icon","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"shipped_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"target_roles","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":true,"generated":""},{"name":"is_published","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_platform_changelog_published","definition":"CREATE INDEX idx_platform_changelog_published ON public.platform_changelog USING btree (is_published) WHERE (is_published = true)"},{"name":"idx_platform_changelog_shipped_at","definition":"CREATE INDEX idx_platform_changelog_shipped_at ON public.platform_changelog USING btree (shipped_at DESC)"},{"name":"platform_changelog_pkey","definition":"CREATE UNIQUE INDEX platform_changelog_pkey ON public.platform_changelog USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_platform_admin(uid())","roles":["authenticated"],"tablename":"platform_changelog","permissive":"PERMISSIVE","policyname":"Platform admins can delete changelog","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"platform_changelog","permissive":"PERMISSIVE","policyname":"Platform admins can insert changelog","schemaname":"public","with_check":"is_platform_admin(uid())"},{"cmd":"UPDATE","qual":"is_platform_admin(uid())","roles":["authenticated"],"tablename":"platform_changelog","permissive":"PERMISSIVE","policyname":"Platform admins can update changelog","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((is_published = true) AND ((cardinality(target_roles) = 0) OR (EXISTS ( SELECT 1\n   FROM user_roles ur\n  WHERE ((ur.user_id = uid()) AND ((ur.role)::text = ANY (platform_changelog.target_roles)))))))","roles":["authenticated"],"tablename":"platform_changelog","permissive":"PERMISSIVE","policyname":"Signed-in users can view targeted published changelog","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_platform_changelog_updated_at","definition":"CREATE TRIGGER trg_platform_changelog_updated_at BEFORE UPDATE ON platform_changelog FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"platform_changelog_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"platform_communication_mode","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"mode","type":"text","default":"'testing'::text","identity":"","not_null":true,"generated":""},{"name":"admin_sink_email","type":"text","default":"'admin@knocklaunch.app'::text","identity":"","not_null":true,"generated":""},{"name":"admin_sink_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"singleton","type":"boolean","default":"true","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"platform_communication_mode_pkey","definition":"CREATE UNIQUE INDEX platform_communication_mode_pkey ON public.platform_communication_mode USING btree (id)"},{"name":"platform_communication_mode_singleton_key","definition":"CREATE UNIQUE INDEX platform_communication_mode_singleton_key ON public.platform_communication_mode USING btree (singleton)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"platform_communication_mode","permissive":"PERMISSIVE","policyname":"All authenticated can read comm mode","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"platform_communication_mode","permissive":"PERMISSIVE","policyname":"Only GodMode can insert comm mode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"UPDATE","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"platform_communication_mode","permissive":"PERMISSIVE","policyname":"Only GodMode can update comm mode","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"trg_log_comm_mode_change","definition":"CREATE TRIGGER trg_log_comm_mode_change BEFORE UPDATE ON platform_communication_mode FOR EACH ROW EXECUTE FUNCTION log_comm_mode_change()"}],"constraints":[{"name":"platform_communication_mode_mode_check","definition":"CHECK (mode = ANY (ARRAY['testing'::text, 'live'::text]))"},{"name":"platform_communication_mode_pkey","definition":"PRIMARY KEY (id)"},{"name":"platform_communication_mode_singleton_key","definition":"UNIQUE (singleton)"}]},{"table":"platform_override_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"actor_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"target_table","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"target_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"platform_override_log_pkey","definition":"CREATE UNIQUE INDEX platform_override_log_pkey ON public.platform_override_log USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"platform_override_log","permissive":"PERMISSIVE","policyname":"pol_insert","schemaname":"public","with_check":"((actor_id = uid()) AND is_platform_admin(uid()))"},{"cmd":"SELECT","qual":"(is_platform_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = platform_override_log.tenant_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role]))))))","roles":["authenticated"],"tablename":"platform_override_log","permissive":"PERMISSIVE","policyname":"pol_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"platform_override_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"portal_links","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"token","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"view_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_portal_links_contact","definition":"CREATE INDEX idx_portal_links_contact ON public.portal_links USING btree (contact_id)"},{"name":"idx_portal_links_tenant","definition":"CREATE INDEX idx_portal_links_tenant ON public.portal_links USING btree (tenant_org_id)"},{"name":"idx_portal_links_token","definition":"CREATE INDEX idx_portal_links_token ON public.portal_links USING btree (token)"},{"name":"portal_links_pkey","definition":"CREATE UNIQUE INDEX portal_links_pkey ON public.portal_links USING btree (id)"},{"name":"portal_links_token_key","definition":"CREATE UNIQUE INDEX portal_links_token_key ON public.portal_links USING btree (token)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = portal_links.tenant_org_id))))","roles":["authenticated"],"tablename":"portal_links","permissive":"PERMISSIVE","policyname":"Tenant members can manage portal links","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = portal_links.tenant_org_id))))"}],"triggers":[],"constraints":[{"name":"portal_links_pkey","definition":"PRIMARY KEY (id)"},{"name":"portal_links_token_key","definition":"UNIQUE (token)"}]},{"table":"profiles","schema":"public","columns":[{"name":"id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"text","default":"'Rep'::text","identity":"","not_null":false,"generated":""},{"name":"active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"company","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_login","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"pin_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_drive_folder_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_provisioned_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_provisioning_status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"drive_provisioning_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"leaddeck_sheet_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"license_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_login_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"tcpa_certified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"assist_opt_in","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"elevenlabs_voice_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_consented_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_consent_typed_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_consent_ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_consent_audio_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_sample_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_enrolled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_clone_disabled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"daily_dial_goal","type":"integer","default":"50","identity":"","not_null":true,"generated":""},{"name":"daily_book_goal","type":"integer","default":"3","identity":"","not_null":true,"generated":""},{"name":"voice_clone_settings","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_profiles_inactive","definition":"CREATE INDEX idx_profiles_inactive ON public.profiles USING btree (id) WHERE (active = false)"},{"name":"idx_profiles_last_login_at","definition":"CREATE INDEX idx_profiles_last_login_at ON public.profiles USING btree (last_login_at)"},{"name":"profiles_email_key","definition":"CREATE UNIQUE INDEX profiles_email_key ON public.profiles USING btree (email)"},{"name":"profiles_pkey","definition":"CREATE UNIQUE INDEX profiles_pkey ON public.profiles USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((id = ( SELECT uid() AS uid)) OR shares_tenant_as_manager_pm(( SELECT uid() AS uid), id))","roles":["public"],"tablename":"profiles","permissive":"PERMISSIVE","policyname":"Managers view tenant team profiles","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"profiles","permissive":"PERMISSIVE","policyname":"profiles_insert_self_or_admin","schemaname":"public","with_check":"((id = ( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin))"},{"cmd":"SELECT","qual":"((id = ( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin))","roles":["authenticated"],"tablename":"profiles","permissive":"PERMISSIVE","policyname":"profiles_select_own_or_admin","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(id = ( SELECT uid() AS uid))","roles":["public"],"tablename":"profiles","permissive":"PERMISSIVE","policyname":"profiles_update_self_no_escalation","schemaname":"public","with_check":"((id = ( SELECT uid() AS uid)) AND profile_authority_unchanged(( SELECT uid() AS uid), role, tenant_org_id))"},{"cmd":"UPDATE","qual":"( SELECT is_system_admin(uid()) AS is_system_admin)","roles":["authenticated"],"tablename":"profiles","permissive":"PERMISSIVE","policyname":"profiles_update_system_admin","schemaname":"public","with_check":"( SELECT is_system_admin(uid()) AS is_system_admin)"},{"cmd":"SELECT","qual":"((id = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM ((security_active_user_tenant_memberships utm_owner\n     JOIN user_roles ur ON (((ur.user_id = utm_owner.user_id) AND (ur.tenant_id = utm_owner.tenant_id))))\n     JOIN security_active_user_tenant_memberships utm_target ON (((utm_target.tenant_id = utm_owner.tenant_id) AND (utm_target.user_id = profiles.id))))\n  WHERE ((utm_owner.user_id = uid()) AND (utm_owner.status = 'active'::text) AND (utm_target.status = 'active'::text) AND ((utm_owner.is_owner = true) OR (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))))","roles":["authenticated"],"tablename":"profiles","permissive":"PERMISSIVE","policyname":"tenant_owners_view_team_profiles_safe","schemaname":"public","with_check":null}],"triggers":[{"name":"audit_trigger_profiles","definition":"CREATE TRIGGER audit_trigger_profiles AFTER INSERT OR DELETE OR UPDATE ON profiles FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"},{"name":"throttle_profile_login_touch","definition":"CREATE TRIGGER throttle_profile_login_touch BEFORE UPDATE OF last_login, last_login_at ON profiles FOR EACH ROW EXECUTE FUNCTION throttle_profile_login_touch()"},{"name":"trg_audit_profile_phone","definition":"CREATE TRIGGER trg_audit_profile_phone AFTER UPDATE OF phone ON profiles FOR EACH ROW EXECUTE FUNCTION audit_phone_change()"},{"name":"trg_knocklaunch_profile_delete_to_auth","definition":"CREATE TRIGGER trg_knocklaunch_profile_delete_to_auth AFTER DELETE ON profiles FOR EACH ROW EXECUTE FUNCTION knocklaunch_sync_profile_delete_to_auth()"},{"name":"trg_knocklaunch_profiles_orphan_email_guard","definition":"CREATE TRIGGER trg_knocklaunch_profiles_orphan_email_guard BEFORE INSERT OR UPDATE OF email ON profiles FOR EACH ROW EXECUTE FUNCTION knocklaunch_remove_orphan_profile_email_conflict()"},{"name":"trg_protect_profile_phone","definition":"CREATE TRIGGER trg_protect_profile_phone BEFORE INSERT OR UPDATE OF phone ON profiles FOR EACH ROW EXECUTE FUNCTION protect_profile_phone()"},{"name":"update_profiles_updated_at","definition":"CREATE TRIGGER update_profiles_updated_at BEFORE UPDATE ON profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"profiles_email_key","definition":"UNIQUE (email)"},{"name":"profiles_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"property_assessments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"assessed_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assessed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"roof_condition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_age","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_material","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"siding_condition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"siding_material","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"gutters_condition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"visible_damage","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimated_cost","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"urgency","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"photos","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_property_assessments_door_id","definition":"CREATE INDEX idx_property_assessments_door_id ON public.property_assessments USING btree (door_id)"},{"name":"idx_property_assessments_priority","definition":"CREATE INDEX idx_property_assessments_priority ON public.property_assessments USING btree (priority_score DESC)"},{"name":"idx_property_assessments_tenant","definition":"CREATE INDEX idx_property_assessments_tenant ON public.property_assessments USING btree (tenant_org_id)"},{"name":"property_assessments_pkey","definition":"CREATE UNIQUE INDEX property_assessments_pkey ON public.property_assessments USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = property_assessments.tenant_org_id))))","roles":["public"],"tablename":"property_assessments","permissive":"PERMISSIVE","policyname":"Tenant members view property assessments","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"property_assessments","permissive":"PERMISSIVE","policyname":"Users create property assessments","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = property_assessments.tenant_org_id))))"}],"triggers":[],"constraints":[{"name":"property_assessments_gutters_condition_check","definition":"CHECK (gutters_condition = ANY (ARRAY['Excellent'::text, 'Good'::text, 'Fair'::text, 'Poor'::text]))"},{"name":"property_assessments_pkey","definition":"PRIMARY KEY (id)"},{"name":"property_assessments_priority_score_check","definition":"CHECK (priority_score >= 1 AND priority_score <= 5)"},{"name":"property_assessments_roof_condition_check","definition":"CHECK (roof_condition = ANY (ARRAY['Excellent'::text, 'Good'::text, 'Fair'::text, 'Poor'::text, 'Severe Damage'::text]))"},{"name":"property_assessments_siding_condition_check","definition":"CHECK (siding_condition = ANY (ARRAY['Excellent'::text, 'Good'::text, 'Fair'::text, 'Poor'::text]))"},{"name":"property_assessments_urgency_check","definition":"CHECK (urgency = ANY (ARRAY['Low'::text, 'Medium'::text, 'High'::text, 'Critical'::text]))"}]},{"table":"property_data_enrichment_status","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"full_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_data_status","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"permit_data_status","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_status","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"last_property_lookup_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_permit_lookup_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_jurisdiction_check_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_retry_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_review_flag","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"pdes_tenant_idx","definition":"CREATE INDEX pdes_tenant_idx ON public.property_data_enrichment_status USING btree (tenant_org_id)"},{"name":"property_data_enrichment_status_pkey","definition":"CREATE UNIQUE INDEX property_data_enrichment_status_pkey ON public.property_data_enrichment_status USING btree (id)"},{"name":"property_data_enrichment_status_tenant_full_address_upsert_idx","definition":"CREATE UNIQUE INDEX property_data_enrichment_status_tenant_full_address_upsert_idx ON public.property_data_enrichment_status USING btree (tenant_org_id, full_address)"},{"name":"property_data_enrichment_status_unique","definition":"CREATE UNIQUE INDEX property_data_enrichment_status_unique ON public.property_data_enrichment_status USING btree (COALESCE(tenant_org_id, '00000000-0000-0000-0000-000000000000'::uuid), lower(full_address))"}],"policies":[{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"property_data_enrichment_status","permissive":"PERMISSIVE","policyname":"pdes read tenant","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"property_data_enrichment_status","permissive":"PERMISSIVE","policyname":"pdes write tenant","schemaname":"public","with_check":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))"}],"triggers":[{"name":"property_data_enrichment_status_updated_at","definition":"CREATE TRIGGER property_data_enrichment_status_updated_at BEFORE UPDATE ON property_data_enrichment_status FOR EACH ROW EXECUTE FUNCTION set_updated_at_simple()"}],"constraints":[{"name":"property_data_enrichment_status_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"property_intelligence","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"mortgage_status","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"mortgage_inferred_from","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mortgage_confidence","type":"text","default":"'low'::text","identity":"","not_null":true,"generated":""},{"name":"mortgage_lender","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mortgage_recorded_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_citizens_insured","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"carrier_detected","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"post_storm_permit","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"post_storm_permit_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"pre_storm_permit_age_days","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"enrichment_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_enriched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_property_intelligence_citizens","definition":"CREATE INDEX idx_property_intelligence_citizens ON public.property_intelligence USING btree (tenant_org_id) WHERE (is_citizens_insured = true)"},{"name":"idx_property_intelligence_mortgage","definition":"CREATE INDEX idx_property_intelligence_mortgage ON public.property_intelligence USING btree (tenant_org_id, mortgage_status) WHERE (mortgage_status = 'active'::text)"},{"name":"idx_property_intelligence_post_storm_permit","definition":"CREATE INDEX idx_property_intelligence_post_storm_permit ON public.property_intelligence USING btree (tenant_org_id) WHERE (post_storm_permit = true)"},{"name":"idx_property_intelligence_tenant_contact","definition":"CREATE INDEX idx_property_intelligence_tenant_contact ON public.property_intelligence USING btree (tenant_org_id, contact_id)"},{"name":"property_intelligence_contact_unique","definition":"CREATE UNIQUE INDEX property_intelligence_contact_unique ON public.property_intelligence USING btree (tenant_org_id, contact_id)"},{"name":"property_intelligence_pkey","definition":"CREATE UNIQUE INDEX property_intelligence_pkey ON public.property_intelligence USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"property_intelligence","permissive":"PERMISSIVE","policyname":"system_admin_delete_property_intelligence","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"property_intelligence","permissive":"PERMISSIVE","policyname":"tenant_members_insert_property_intelligence","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"property_intelligence","permissive":"PERMISSIVE","policyname":"tenant_members_select_property_intelligence","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"property_intelligence","permissive":"PERMISSIVE","policyname":"tenant_members_update_property_intelligence","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))"}],"triggers":[{"name":"trg_property_intelligence_updated_at","definition":"CREATE TRIGGER trg_property_intelligence_updated_at BEFORE UPDATE ON property_intelligence FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"property_intelligence_contact_unique","definition":"UNIQUE (tenant_org_id, contact_id)"},{"name":"property_intelligence_mortgage_confidence_check","definition":"CHECK (mortgage_confidence = ANY (ARRAY['high'::text, 'medium'::text, 'low'::text]))"},{"name":"property_intelligence_mortgage_inferred_from_check","definition":"CHECK (mortgage_inferred_from IS NULL OR (mortgage_inferred_from = ANY (ARRAY['fdor'::text, 'recorder'::text, 'hybrid'::text])))"},{"name":"property_intelligence_mortgage_status_check","definition":"CHECK (mortgage_status = ANY (ARRAY['active'::text, 'paid_off'::text, 'unknown'::text]))"},{"name":"property_intelligence_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"property_jurisdiction_matches","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"full_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"parcel_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"latitude","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"longitude","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"county","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":"'FL'::text","identity":"","not_null":false,"generated":""},{"name":"permitting_authority","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"jurisdiction_confidence","type":"text","default":"'low'::text","identity":"","not_null":true,"generated":""},{"name":"jurisdiction_method","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"matched_boundary_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_override_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_override_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"manual_verification_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"property_jurisdiction_matches_addr_idx","definition":"CREATE INDEX property_jurisdiction_matches_addr_idx ON public.property_jurisdiction_matches USING btree (lower(full_address))"},{"name":"property_jurisdiction_matches_parcel_idx","definition":"CREATE INDEX property_jurisdiction_matches_parcel_idx ON public.property_jurisdiction_matches USING btree (parcel_id) WHERE (parcel_id IS NOT NULL)"},{"name":"property_jurisdiction_matches_pkey","definition":"CREATE UNIQUE INDEX property_jurisdiction_matches_pkey ON public.property_jurisdiction_matches USING btree (id)"},{"name":"property_jurisdiction_matches_tenant_idx","definition":"CREATE INDEX property_jurisdiction_matches_tenant_idx ON public.property_jurisdiction_matches USING btree (tenant_org_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"property_jurisdiction_matches","permissive":"PERMISSIVE","policyname":"jurisdiction insert tenant","schemaname":"public","with_check":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"property_jurisdiction_matches","permissive":"PERMISSIVE","policyname":"jurisdiction read tenant","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"property_jurisdiction_matches","permissive":"PERMISSIVE","policyname":"jurisdiction update tenant","schemaname":"public","with_check":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))"}],"triggers":[{"name":"property_jurisdiction_matches_updated_at","definition":"CREATE TRIGGER property_jurisdiction_matches_updated_at BEFORE UPDATE ON property_jurisdiction_matches FOR EACH ROW EXECUTE FUNCTION set_updated_at_simple()"}],"constraints":[{"name":"property_jurisdiction_matches_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"property_permits","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"full_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parcel_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"issue_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"final_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"expiration_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"contractor_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contractor_license","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"work_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"declared_value","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"square_footage","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_jurisdiction","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_related","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"confidence_score","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"manually_verified","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"verified_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"property_permits_addr_idx","definition":"CREATE INDEX property_permits_addr_idx ON public.property_permits USING btree (lower(full_address))"},{"name":"property_permits_contact_idx","definition":"CREATE INDEX property_permits_contact_idx ON public.property_permits USING btree (contact_id)"},{"name":"property_permits_pkey","definition":"CREATE UNIQUE INDEX property_permits_pkey ON public.property_permits USING btree (id)"},{"name":"property_permits_property_idx","definition":"CREATE INDEX property_permits_property_idx ON public.property_permits USING btree (property_id)"},{"name":"property_permits_roof_idx","definition":"CREATE INDEX property_permits_roof_idx ON public.property_permits USING btree (roof_related, issue_date DESC)"},{"name":"property_permits_tenant_idx","definition":"CREATE INDEX property_permits_tenant_idx ON public.property_permits USING btree (tenant_org_id)"},{"name":"property_permits_tenant_source_permit_upsert_idx","definition":"CREATE UNIQUE INDEX property_permits_tenant_source_permit_upsert_idx ON public.property_permits USING btree (tenant_org_id, source_jurisdiction, permit_number)"},{"name":"property_permits_unique_record","definition":"CREATE UNIQUE INDEX property_permits_unique_record ON public.property_permits USING btree (tenant_org_id, source_jurisdiction, permit_number) WHERE (permit_number IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"property_permits","permissive":"PERMISSIVE","policyname":"permits read tenant","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))","roles":["authenticated"],"tablename":"property_permits","permissive":"PERMISSIVE","policyname":"permits write tenant","schemaname":"public","with_check":"((tenant_org_id IS NULL) OR is_tenant_member((tenant_org_id)::text))"}],"triggers":[{"name":"property_permits_updated_at","definition":"CREATE TRIGGER property_permits_updated_at BEFORE UPDATE ON property_permits FOR EACH ROW EXECUTE FUNCTION set_updated_at_simple()"}],"constraints":[{"name":"property_permits_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"proposal_profiles","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"profile_key","type":"text","default":"'default'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"number_prefix","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"renderer_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"proposal_profiles_one_active_per_tenant_idx","definition":"CREATE UNIQUE INDEX proposal_profiles_one_active_per_tenant_idx ON public.proposal_profiles USING btree (tenant_id) WHERE (status = 'active'::text)"},{"name":"proposal_profiles_pkey","definition":"CREATE UNIQUE INDEX proposal_profiles_pkey ON public.proposal_profiles USING btree (id)"},{"name":"proposal_profiles_tenant_id_profile_key_key","definition":"CREATE UNIQUE INDEX proposal_profiles_tenant_id_profile_key_key ON public.proposal_profiles USING btree (tenant_id, profile_key)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["public"],"tablename":"proposal_profiles","permissive":"PERMISSIVE","policyname":"proposal_profiles_member_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"proposal_profiles_pkey","definition":"PRIMARY KEY (id)"},{"name":"proposal_profiles_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'inactive'::text]))"},{"name":"proposal_profiles_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"proposal_profiles_tenant_id_profile_key_key","definition":"UNIQUE (tenant_id, profile_key)"},{"name":"proposal_profiles_version_check","definition":"CHECK (version > 0)"}]},{"table":"proposal_sequences","schema":"public","columns":[{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"proposal_year","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"number_prefix","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"last_sequence","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"proposal_sequences_pkey","definition":"CREATE UNIQUE INDEX proposal_sequences_pkey ON public.proposal_sequences USING btree (tenant_id, proposal_year, number_prefix)"}],"policies":[],"triggers":[],"constraints":[{"name":"proposal_sequences_last_sequence_check","definition":"CHECK (last_sequence >= 0)"},{"name":"proposal_sequences_pkey","definition":"PRIMARY KEY (tenant_id, proposal_year, number_prefix)"},{"name":"proposal_sequences_proposal_year_check","definition":"CHECK (proposal_year >= 2000 AND proposal_year <= 2200)"},{"name":"proposal_sequences_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"proposal_versions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"proposal_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"version","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"snapshot","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"snapshot_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"render_bucket","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"render_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"render_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rendered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"proposal_versions_pkey","definition":"CREATE UNIQUE INDEX proposal_versions_pkey ON public.proposal_versions USING btree (id)"},{"name":"proposal_versions_proposal_id_version_key","definition":"CREATE UNIQUE INDEX proposal_versions_proposal_id_version_key ON public.proposal_versions USING btree (proposal_id, version)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["public"],"tablename":"proposal_versions","permissive":"PERMISSIVE","policyname":"proposal_versions_member_read","schemaname":"public","with_check":null}],"triggers":[{"name":"kl_proposal_version_content_immutable","definition":"CREATE TRIGGER kl_proposal_version_content_immutable BEFORE UPDATE ON proposal_versions FOR EACH ROW EXECUTE FUNCTION kl_proposal_version_content_immutable()"}],"constraints":[{"name":"proposal_versions_pkey","definition":"PRIMARY KEY (id)"},{"name":"proposal_versions_proposal_id_fkey","definition":"FOREIGN KEY (proposal_id) REFERENCES proposals(id) ON DELETE CASCADE"},{"name":"proposal_versions_proposal_id_version_key","definition":"UNIQUE (proposal_id, version)"},{"name":"proposal_versions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"proposal_versions_version_check","definition":"CHECK (version > 0)"}]},{"table":"proposals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"profile_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"proposal_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"current_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"idempotency_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_opportunity_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"offer_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"selected_option_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pricing_mode","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"currency","type":"text","default":"'USD'::text","identity":"","not_null":true,"generated":""},{"name":"recipient_snapshot","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"context_snapshot","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"line_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"subtotal_amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"adjustment_amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"tax_amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"total_amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"deposit_amount","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"balance_amount","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"terms","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"internal_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"profile_snapshot","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"brand_snapshot","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"commercial_snapshot","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"render_bucket","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"render_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"render_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"render_content_fingerprint","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rendered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"accepted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"declined_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"voided_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"proposals_pkey","definition":"CREATE UNIQUE INDEX proposals_pkey ON public.proposals USING btree (id)"},{"name":"proposals_tenant_contact_idx","definition":"CREATE INDEX proposals_tenant_contact_idx ON public.proposals USING btree (tenant_id, source_contact_id, updated_at DESC)"},{"name":"proposals_tenant_event_idx","definition":"CREATE INDEX proposals_tenant_event_idx ON public.proposals USING btree (tenant_id, source_event_id, updated_at DESC)"},{"name":"proposals_tenant_id_proposal_number_key","definition":"CREATE UNIQUE INDEX proposals_tenant_id_proposal_number_key ON public.proposals USING btree (tenant_id, proposal_number)"},{"name":"proposals_tenant_idempotency_idx","definition":"CREATE UNIQUE INDEX proposals_tenant_idempotency_idx ON public.proposals USING btree (tenant_id, idempotency_key) WHERE (idempotency_key IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["public"],"tablename":"proposals","permissive":"PERMISSIVE","policyname":"proposals_member_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"proposals_current_version_check","definition":"CHECK (current_version > 0)"},{"name":"proposals_pkey","definition":"PRIMARY KEY (id)"},{"name":"proposals_profile_id_fkey","definition":"FOREIGN KEY (profile_id) REFERENCES proposal_profiles(id)"},{"name":"proposals_source_contact_id_fkey","definition":"FOREIGN KEY (source_contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"proposals_source_event_id_fkey","definition":"FOREIGN KEY (source_event_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"proposals_source_opportunity_id_fkey","definition":"FOREIGN KEY (source_opportunity_id) REFERENCES business_opportunities(id) ON DELETE SET NULL"},{"name":"proposals_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'sent'::text, 'approved'::text, 'accepted'::text, 'declined'::text, 'paid'::text, 'void'::text]))"},{"name":"proposals_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"proposals_tenant_id_proposal_number_key","definition":"UNIQUE (tenant_id, proposal_number)"},{"name":"proposals_verified_render_contract","definition":"CHECK (render_bucket IS NULL AND render_path IS NULL AND render_hash IS NULL AND render_content_fingerprint IS NULL AND rendered_at IS NULL OR render_bucket IS NOT NULL AND render_path IS NOT NULL AND render_hash IS NOT NULL AND render_content_fingerprint IS NOT NULL AND rendered_at IS NOT NULL)"}]},{"table":"qr_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"intent_type","type":"text","default":"'lead'::text","identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_source","type":"text","default":"'qr'::text","identity":"","not_null":false,"generated":""},{"name":"utm_medium","type":"text","default":"'offline'::text","identity":"","not_null":false,"generated":""},{"name":"utm_campaign","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"starts_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"ends_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_qr_campaigns_tenant_created","definition":"CREATE INDEX idx_qr_campaigns_tenant_created ON public.qr_campaigns USING btree (tenant_id, created_at DESC)"},{"name":"qr_campaigns_pkey","definition":"CREATE UNIQUE INDEX qr_campaigns_pkey ON public.qr_campaigns USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"qr_campaigns_intent_check","definition":"CHECK (intent_type = ANY (ARRAY['lead'::text, 'booking'::text, 'profile'::text, 'review'::text, 'service'::text, 'platform'::text, 'custom'::text]))"},{"name":"qr_campaigns_pkey","definition":"PRIMARY KEY (id)"},{"name":"qr_campaigns_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"qr_campaigns_tenant_or_platform_check","definition":"CHECK (tenant_id IS NOT NULL OR intent_type = 'platform'::text)"}]},{"table":"qr_codes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"short_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"type","type":"text","default":"'lead'::text","identity":"","not_null":true,"generated":""},{"name":"destination_mode","type":"text","default":"'external_url'::text","identity":"","not_null":true,"generated":""},{"name":"destination_value","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"fallback_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rules","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"design","type":"jsonb","default":"'{\"frameText\": \"Scan to connect\", \"background\": \"#ffffff\", \"foreground\": \"#111827\", \"logoEnabled\": false, \"errorCorrectionLevel\": \"H\"}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_qr_codes_short_code","definition":"CREATE INDEX idx_qr_codes_short_code ON public.qr_codes USING btree (short_code)"},{"name":"idx_qr_codes_tenant_created","definition":"CREATE INDEX idx_qr_codes_tenant_created ON public.qr_codes USING btree (tenant_id, created_at DESC)"},{"name":"qr_codes_pkey","definition":"CREATE UNIQUE INDEX qr_codes_pkey ON public.qr_codes USING btree (id)"},{"name":"qr_codes_short_code_key","definition":"CREATE UNIQUE INDEX qr_codes_short_code_key ON public.qr_codes USING btree (short_code)"}],"policies":[],"triggers":[],"constraints":[{"name":"qr_codes_campaign_id_fkey","definition":"FOREIGN KEY (campaign_id) REFERENCES qr_campaigns(id) ON DELETE SET NULL"},{"name":"qr_codes_destination_mode_check","definition":"CHECK (destination_mode = ANY (ARRAY['internal_route'::text, 'external_url'::text, 'rules'::text]))"},{"name":"qr_codes_pkey","definition":"PRIMARY KEY (id)"},{"name":"qr_codes_short_code_format","definition":"CHECK (short_code ~ '^[a-zA-Z0-9_-]{5,48}$'::text)"},{"name":"qr_codes_short_code_key","definition":"UNIQUE (short_code)"},{"name":"qr_codes_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"qr_codes_tenant_or_platform_check","definition":"CHECK (tenant_id IS NOT NULL OR type = 'platform'::text)"},{"name":"qr_codes_type_check","definition":"CHECK (type = ANY (ARRAY['lead'::text, 'booking'::text, 'profile'::text, 'review'::text, 'service'::text, 'platform'::text, 'custom'::text]))"}]},{"table":"qr_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"qr_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":"'scan'::text","identity":"","not_null":true,"generated":""},{"name":"session_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"device_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"destination_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_qr_events_campaign_created","definition":"CREATE INDEX idx_qr_events_campaign_created ON public.qr_events USING btree (campaign_id, created_at DESC)"},{"name":"idx_qr_events_qr_created","definition":"CREATE INDEX idx_qr_events_qr_created ON public.qr_events USING btree (qr_id, created_at DESC)"},{"name":"idx_qr_events_tenant_created","definition":"CREATE INDEX idx_qr_events_tenant_created ON public.qr_events USING btree (tenant_id, created_at DESC)"},{"name":"qr_events_pkey","definition":"CREATE UNIQUE INDEX qr_events_pkey ON public.qr_events USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"qr_events_campaign_id_fkey","definition":"FOREIGN KEY (campaign_id) REFERENCES qr_campaigns(id) ON DELETE SET NULL"},{"name":"qr_events_event_type_check","definition":"CHECK (event_type = ANY (ARRAY['scan'::text, 'redirect'::text, 'conversion'::text, 'error'::text]))"},{"name":"qr_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"qr_events_qr_id_fkey","definition":"FOREIGN KEY (qr_id) REFERENCES qr_codes(id) ON DELETE CASCADE"},{"name":"qr_events_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"queue_callbacks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"ring_group_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempts","type":"smallint","default":"0","identity":"","not_null":true,"generated":""},{"name":"last_attempt_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_queue_callbacks_tenant_status","definition":"CREATE INDEX idx_queue_callbacks_tenant_status ON public.queue_callbacks USING btree (tenant_org_id, status, requested_at)"},{"name":"queue_callbacks_pkey","definition":"CREATE UNIQUE INDEX queue_callbacks_pkey ON public.queue_callbacks USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"queue_callbacks","permissive":"PERMISSIVE","policyname":"queue_callbacks_delete_managers","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"queue_callbacks","permissive":"PERMISSIVE","policyname":"queue_callbacks_insert_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"queue_callbacks","permissive":"PERMISSIVE","policyname":"queue_callbacks_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_manager_or_higher(uid(), tenant_org_id) OR (assigned_user_id = uid()))","roles":["authenticated"],"tablename":"queue_callbacks","permissive":"PERMISSIVE","policyname":"queue_callbacks_update_assigned_or_manager","schemaname":"public","with_check":"(is_manager_or_higher(uid(), tenant_org_id) OR (assigned_user_id = uid()))"}],"triggers":[{"name":"trg_queue_callbacks_updated_at","definition":"CREATE TRIGGER trg_queue_callbacks_updated_at BEFORE UPDATE ON queue_callbacks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"queue_callbacks_pkey","definition":"PRIMARY KEY (id)"},{"name":"queue_callbacks_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'in_progress'::text, 'completed'::text, 'failed'::text, 'cancelled'::text]))"}]},{"table":"realtor_campaign_activities","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"activity_type","type":"text","default":"'note'::text","identity":"","not_null":true,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rca_campaign","definition":"CREATE INDEX idx_rca_campaign ON public.realtor_campaign_activities USING btree (campaign_id)"},{"name":"idx_rca_created","definition":"CREATE INDEX idx_rca_created ON public.realtor_campaign_activities USING btree (created_at DESC)"},{"name":"idx_rca_property","definition":"CREATE INDEX idx_rca_property ON public.realtor_campaign_activities USING btree (property_id)"},{"name":"idx_rca_tenant","definition":"CREATE INDEX idx_rca_tenant ON public.realtor_campaign_activities USING btree (tenant_id)"},{"name":"realtor_campaign_activities_pkey","definition":"CREATE UNIQUE INDEX realtor_campaign_activities_pkey ON public.realtor_campaign_activities USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_activities","permissive":"PERMISSIVE","policyname":"rca_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_campaign_activities","permissive":"PERMISSIVE","policyname":"rca_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_activities","permissive":"PERMISSIVE","policyname":"rca_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_activities","permissive":"PERMISSIVE","policyname":"rca_update_owner","schemaname":"public","with_check":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())"}],"triggers":[],"constraints":[{"name":"realtor_campaign_activities_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"realtor_campaign_outreach_queue","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_property_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"channel","type":"text","default":"'call'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"script_preview","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rcoq_assigned","definition":"CREATE INDEX idx_rcoq_assigned ON public.realtor_campaign_outreach_queue USING btree (assigned_user_id, status)"},{"name":"idx_rcoq_campaign_property","definition":"CREATE INDEX idx_rcoq_campaign_property ON public.realtor_campaign_outreach_queue USING btree (campaign_property_id)"},{"name":"idx_rcoq_tenant_campaign","definition":"CREATE INDEX idx_rcoq_tenant_campaign ON public.realtor_campaign_outreach_queue USING btree (tenant_id, campaign_id, status)"},{"name":"realtor_campaign_outreach_queue_pkey","definition":"CREATE UNIQUE INDEX realtor_campaign_outreach_queue_pkey ON public.realtor_campaign_outreach_queue USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_outreach_queue","permissive":"PERMISSIVE","policyname":"rcoq_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_campaign_outreach_queue","permissive":"PERMISSIVE","policyname":"rcoq_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_outreach_queue","permissive":"PERMISSIVE","policyname":"rcoq_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_campaign_outreach_queue","permissive":"PERMISSIVE","policyname":"rcoq_update_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_rcoq_tenant_guard","definition":"CREATE TRIGGER trg_rcoq_tenant_guard BEFORE INSERT OR UPDATE ON realtor_campaign_outreach_queue FOR EACH ROW EXECUTE FUNCTION trg_rcoq_tenant_guard()"},{"name":"trg_rcoq_updated_at","definition":"CREATE TRIGGER trg_rcoq_updated_at BEFORE UPDATE ON realtor_campaign_outreach_queue FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"realtor_campaign_outreach_queue_channel_check","definition":"CHECK (channel = ANY (ARRAY['call'::text, 'door_knock'::text, 'sms_preview'::text, 'email_preview'::text]))"},{"name":"realtor_campaign_outreach_queue_pkey","definition":"PRIMARY KEY (id)"},{"name":"realtor_campaign_outreach_queue_status_check","definition":"CHECK (status = ANY (ARRAY['queued'::text, 'in_progress'::text, 'completed'::text, 'skipped'::text, 'do_not_contact'::text]))"}]},{"table":"realtor_campaign_properties","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"added_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"added_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"last_action_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rcp_campaign","definition":"CREATE INDEX idx_rcp_campaign ON public.realtor_campaign_properties USING btree (campaign_id)"},{"name":"idx_rcp_property","definition":"CREATE INDEX idx_rcp_property ON public.realtor_campaign_properties USING btree (property_id)"},{"name":"idx_rcp_status","definition":"CREATE INDEX idx_rcp_status ON public.realtor_campaign_properties USING btree (status)"},{"name":"idx_rcp_tenant","definition":"CREATE INDEX idx_rcp_tenant ON public.realtor_campaign_properties USING btree (tenant_id)"},{"name":"realtor_campaign_properties_campaign_id_property_id_key","definition":"CREATE UNIQUE INDEX realtor_campaign_properties_campaign_id_property_id_key ON public.realtor_campaign_properties USING btree (campaign_id, property_id)"},{"name":"realtor_campaign_properties_pkey","definition":"CREATE UNIQUE INDEX realtor_campaign_properties_pkey ON public.realtor_campaign_properties USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_properties","permissive":"PERMISSIVE","policyname":"rcp_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_campaign_properties","permissive":"PERMISSIVE","policyname":"rcp_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaign_properties","permissive":"PERMISSIVE","policyname":"rcp_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_campaign_properties","permissive":"PERMISSIVE","policyname":"rcp_update_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_rcp_tenant_guard","definition":"CREATE TRIGGER trg_rcp_tenant_guard BEFORE INSERT OR UPDATE ON realtor_campaign_properties FOR EACH ROW EXECUTE FUNCTION realtor_campaign_property_tenant_guard()"},{"name":"trg_rcp_updated","definition":"CREATE TRIGGER trg_rcp_updated BEFORE UPDATE ON realtor_campaign_properties FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"realtor_campaign_properties_campaign_id_property_id_key","definition":"UNIQUE (campaign_id, property_id)"},{"name":"realtor_campaign_properties_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"realtor_campaigns","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"campaign_type","type":"text","default":"'custom'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"target_area","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip_codes","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"tags","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"script_template","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sms_template","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"landing_page_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approval_status","type":"text","default":"'not_required'::text","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_realtor_campaigns_status","definition":"CREATE INDEX idx_realtor_campaigns_status ON public.realtor_campaigns USING btree (status)"},{"name":"idx_realtor_campaigns_tenant","definition":"CREATE INDEX idx_realtor_campaigns_tenant ON public.realtor_campaigns USING btree (tenant_id)"},{"name":"realtor_campaigns_pkey","definition":"CREATE UNIQUE INDEX realtor_campaigns_pkey ON public.realtor_campaigns USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaigns","permissive":"PERMISSIVE","policyname":"rc_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_campaigns","permissive":"PERMISSIVE","policyname":"rc_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_campaigns","permissive":"PERMISSIVE","policyname":"rc_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_campaigns","permissive":"PERMISSIVE","policyname":"rc_update_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_rc_updated","definition":"CREATE TRIGGER trg_rc_updated BEFORE UPDATE ON realtor_campaigns FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"realtor_campaigns_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"realtor_lead_assignments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"previous_assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_assigned_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rla_lead","definition":"CREATE INDEX idx_rla_lead ON public.realtor_lead_assignments USING btree (lead_id)"},{"name":"idx_rla_tenant","definition":"CREATE INDEX idx_rla_tenant ON public.realtor_lead_assignments USING btree (tenant_id)"},{"name":"realtor_lead_assignments_pkey","definition":"CREATE UNIQUE INDEX realtor_lead_assignments_pkey ON public.realtor_lead_assignments USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_lead_assignments","permissive":"PERMISSIVE","policyname":"rla_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_lead_assignments","permissive":"PERMISSIVE","policyname":"rla_select_member","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"realtor_lead_assignments_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"realtor_properties","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"parcel_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_mailing_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"occupancy_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"absentee_owner","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"estimated_equity","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_sale_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_tags","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"event_tags","type":"text[]","default":"ARRAY[]::text[]","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_realtor_properties_address","definition":"CREATE INDEX idx_realtor_properties_address ON public.realtor_properties USING btree (lower(address))"},{"name":"idx_realtor_properties_tenant","definition":"CREATE INDEX idx_realtor_properties_tenant ON public.realtor_properties USING btree (tenant_id)"},{"name":"idx_realtor_properties_zip","definition":"CREATE INDEX idx_realtor_properties_zip ON public.realtor_properties USING btree (zip)"},{"name":"realtor_properties_pkey","definition":"CREATE UNIQUE INDEX realtor_properties_pkey ON public.realtor_properties USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_properties","permissive":"PERMISSIVE","policyname":"rp_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_properties","permissive":"PERMISSIVE","policyname":"rp_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_properties","permissive":"PERMISSIVE","policyname":"rp_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_properties","permissive":"PERMISSIVE","policyname":"rp_update_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_rp_updated","definition":"CREATE TRIGGER trg_rp_updated BEFORE UPDATE ON realtor_properties FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"realtor_properties_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"realtor_property_contacts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"relationship_type","type":"text","default":"'owner'::text","identity":"","not_null":false,"generated":""},{"name":"is_primary","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rpc_contact","definition":"CREATE INDEX idx_rpc_contact ON public.realtor_property_contacts USING btree (contact_id)"},{"name":"idx_rpc_property","definition":"CREATE INDEX idx_rpc_property ON public.realtor_property_contacts USING btree (property_id)"},{"name":"idx_rpc_tenant","definition":"CREATE INDEX idx_rpc_tenant ON public.realtor_property_contacts USING btree (tenant_id)"},{"name":"realtor_property_contacts_pkey","definition":"CREATE UNIQUE INDEX realtor_property_contacts_pkey ON public.realtor_property_contacts USING btree (id)"},{"name":"realtor_property_contacts_property_id_contact_id_relationsh_key","definition":"CREATE UNIQUE INDEX realtor_property_contacts_property_id_contact_id_relationsh_key ON public.realtor_property_contacts USING btree (property_id, contact_id, relationship_type)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_property_contacts","permissive":"PERMISSIVE","policyname":"rpc_delete_member","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_property_contacts","permissive":"PERMISSIVE","policyname":"rpc_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_property_contacts","permissive":"PERMISSIVE","policyname":"rpc_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_property_contacts","permissive":"PERMISSIVE","policyname":"rpc_update_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[],"constraints":[{"name":"realtor_property_contacts_pkey","definition":"PRIMARY KEY (id)"},{"name":"realtor_property_contacts_property_id_contact_id_relationsh_key","definition":"UNIQUE (property_id, contact_id, relationship_type)"}]},{"table":"realtor_reports","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"report_type","type":"text","default":"'property_market_snapshot'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'requested'::text","identity":"","not_null":true,"generated":""},{"name":"requested_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"requested_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"appointment_set_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"delivery_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_rr_property","definition":"CREATE INDEX idx_rr_property ON public.realtor_reports USING btree (property_id)"},{"name":"idx_rr_status","definition":"CREATE INDEX idx_rr_status ON public.realtor_reports USING btree (status)"},{"name":"idx_rr_tenant","definition":"CREATE INDEX idx_rr_tenant ON public.realtor_reports USING btree (tenant_id)"},{"name":"realtor_reports_pkey","definition":"CREATE UNIQUE INDEX realtor_reports_pkey ON public.realtor_reports USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_reports","permissive":"PERMISSIVE","policyname":"rr_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_reports","permissive":"PERMISSIVE","policyname":"rr_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_reports","permissive":"PERMISSIVE","policyname":"rr_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"realtor_reports","permissive":"PERMISSIVE","policyname":"rr_update_owner","schemaname":"public","with_check":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())"}],"triggers":[{"name":"trg_rr_updated","definition":"CREATE TRIGGER trg_rr_updated BEFORE UPDATE ON realtor_reports FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"realtor_reports_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"realtor_transactions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"transaction_side","type":"realtor_transaction_side","default":"'listing_side'::realtor_transaction_side","identity":"","not_null":true,"generated":""},{"name":"status","type":"realtor_transaction_status","default":"'pending'::realtor_transaction_status","identity":"","not_null":true,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mls_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sale_price","type":"numeric(14,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"commission_pct","type":"numeric(6,3)","default":null,"identity":"","not_null":false,"generated":""},{"name":"gross_commission","type":"numeric(14,2)","default":"((COALESCE(sale_price, (0)::numeric) * COALESCE(commission_pct, (0)::numeric)) / (100)::numeric)","identity":"","not_null":false,"generated":"s"},{"name":"split_pct_to_agent","type":"numeric(6,3)","default":"100","identity":"","not_null":false,"generated":""},{"name":"brokerage_fee","type":"numeric(14,2)","default":"0","identity":"","not_null":false,"generated":""},{"name":"referral_fee_pct","type":"numeric(6,3)","default":"0","identity":"","not_null":false,"generated":""},{"name":"net_to_agent","type":"numeric(14,2)","default":"((((((COALESCE(sale_price, (0)::numeric) * COALESCE(commission_pct, (0)::numeric)) / (100)::numeric) * COALESCE(split_pct_to_agent, (100)::numeric)) / (100)::numeric) * ((1)::numeric - (COALESCE(referral_fee_pct, (0)::numeric) / (100)::numeric))) - COALESCE(brokerage_fee, (0)::numeric))","identity":"","not_null":false,"generated":"s"},{"name":"expected_close_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"actual_close_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_realtor_transactions_close","definition":"CREATE INDEX idx_realtor_transactions_close ON public.realtor_transactions USING btree (tenant_id, expected_close_date)"},{"name":"idx_realtor_transactions_contact","definition":"CREATE INDEX idx_realtor_transactions_contact ON public.realtor_transactions USING btree (contact_id)"},{"name":"idx_realtor_transactions_status","definition":"CREATE INDEX idx_realtor_transactions_status ON public.realtor_transactions USING btree (tenant_id, status)"},{"name":"idx_realtor_transactions_tenant","definition":"CREATE INDEX idx_realtor_transactions_tenant ON public.realtor_transactions USING btree (tenant_id)"},{"name":"realtor_transactions_pkey","definition":"CREATE UNIQUE INDEX realtor_transactions_pkey ON public.realtor_transactions USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_owner(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_transactions","permissive":"PERMISSIVE","policyname":"rt_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"realtor_transactions","permissive":"PERMISSIVE","policyname":"rt_insert_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_id)","roles":["authenticated"],"tablename":"realtor_transactions","permissive":"PERMISSIVE","policyname":"rt_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_id) AND (is_tenant_owner(uid(), tenant_id) OR (assigned_to = (jwt() ->> 'email'::text)) OR (assigned_to = (uid())::text)))","roles":["authenticated"],"tablename":"realtor_transactions","permissive":"PERMISSIVE","policyname":"rt_update_member","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_id)"}],"triggers":[{"name":"trg_realtor_transactions_updated_at","definition":"CREATE TRIGGER trg_realtor_transactions_updated_at BEFORE UPDATE ON realtor_transactions FOR EACH ROW EXECUTE FUNCTION touch_realtor_transactions_updated_at()"}],"constraints":[{"name":"realtor_transactions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"reassigned_number_checks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"date_used","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"date_source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":"'fcc_rnd'::text","identity":"","not_null":true,"generated":""},{"name":"rnd_response","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"vendor_reference_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rnd_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"raw_response","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"checked_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rnd_tenant_phone","definition":"CREATE INDEX idx_rnd_tenant_phone ON public.reassigned_number_checks USING btree (tenant_org_id, phone_normalized, checked_at DESC)"},{"name":"reassigned_number_checks_pkey","definition":"CREATE UNIQUE INDEX reassigned_number_checks_pkey ON public.reassigned_number_checks USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"reassigned_number_checks","permissive":"PERMISSIVE","policyname":"tenant_members_insert_rnd","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"reassigned_number_checks","permissive":"PERMISSIVE","policyname":"tenant_members_view_rnd","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"reassigned_number_checks_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"rebuttal_usage_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"call_session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rebuttal_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"objection_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rebuttal_length","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rue_lead","definition":"CREATE INDEX idx_rue_lead ON public.rebuttal_usage_events USING btree (lead_id)"},{"name":"idx_rue_rebuttal","definition":"CREATE INDEX idx_rue_rebuttal ON public.rebuttal_usage_events USING btree (rebuttal_id)"},{"name":"idx_rue_tenant_created","definition":"CREATE INDEX idx_rue_tenant_created ON public.rebuttal_usage_events USING btree (tenant_org_id, created_at DESC)"},{"name":"rebuttal_usage_events_pkey","definition":"CREATE UNIQUE INDEX rebuttal_usage_events_pkey ON public.rebuttal_usage_events USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"rebuttal_usage_events","permissive":"PERMISSIVE","policyname":"Tenant members can insert rebuttal usage","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) AND (user_id = uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin())","roles":["authenticated"],"tablename":"rebuttal_usage_events","permissive":"PERMISSIVE","policyname":"Tenant members can view rebuttal usage","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"rebuttal_usage_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"rebuttal_usage_events_source_check","definition":"CHECK (source = ANY (ARRAY['live_coach'::text, 'rescue_panel'::text, 'save_the_sale'::text, 'manual'::text]))"}]},{"table":"referrals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"from_tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"person_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referral_type","type":"text","default":"'general'::text","identity":"","not_null":true,"generated":""},{"name":"referral_status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"urgency","type":"text","default":"'normal'::text","identity":"","not_null":false,"generated":""},{"name":"contact_data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_referrals_from_tenant","definition":"CREATE INDEX idx_referrals_from_tenant ON public.referrals USING btree (from_tenant_id)"},{"name":"idx_referrals_status","definition":"CREATE INDEX idx_referrals_status ON public.referrals USING btree (referral_status)"},{"name":"idx_referrals_to_tenant","definition":"CREATE INDEX idx_referrals_to_tenant ON public.referrals USING btree (to_tenant_id)"},{"name":"referrals_pkey","definition":"CREATE UNIQUE INDEX referrals_pkey ON public.referrals USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"referrals","permissive":"PERMISSIVE","policyname":"members_create_referrals","schemaname":"public","with_check":"is_tenant_member((from_tenant_id)::text)"},{"cmd":"UPDATE","qual":"(is_tenant_member((from_tenant_id)::text) OR is_tenant_member((to_tenant_id)::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"referrals","permissive":"PERMISSIVE","policyname":"participants_update_referrals","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(is_tenant_member((from_tenant_id)::text) OR is_tenant_member((to_tenant_id)::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"referrals","permissive":"PERMISSIVE","policyname":"participants_view_referrals","schemaname":"public","with_check":null}],"triggers":[{"name":"update_referrals_updated_at","definition":"CREATE TRIGGER update_referrals_updated_at BEFORE UPDATE ON referrals FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"referrals_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"rep_auth_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"rep_email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"result","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"rep_auth_log_pkey","definition":"CREATE UNIQUE INDEX rep_auth_log_pkey ON public.rep_auth_log USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"rep_auth_log","permissive":"PERMISSIVE","policyname":"platform_admin_view_rep_auth_log","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"rep_auth_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"rep_leads","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'Active'::text","identity":"","not_null":false,"generated":""},{"name":"stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_rep_leads_email","definition":"CREATE INDEX idx_rep_leads_email ON public.rep_leads USING btree (rep_email)"},{"name":"idx_rep_leads_tenant","definition":"CREATE INDEX idx_rep_leads_tenant ON public.rep_leads USING btree (tenant_org_id)"},{"name":"rep_leads_pkey","definition":"CREATE UNIQUE INDEX rep_leads_pkey ON public.rep_leads USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"rep_leads_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(rep_email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text)","roles":["public"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"rep_leads_self_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(rep_email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text)","roles":["public"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"rep_leads_self_update","schemaname":"public","with_check":"(rep_email = (( SELECT users.email\n   FROM users\n  WHERE (users.id = uid())))::text)"},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"rep_leads_tenant_owner_admin","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))"},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"rl_all","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (rep_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"tenant_users_delete_rep_leads","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"tenant_users_insert_rep_leads","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (rep_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (rep_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"tenant_users_update_rep_leads","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (rep_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (rep_leads.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"rep_leads","permissive":"PERMISSIVE","policyname":"tenant_users_view_rep_leads","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"rep_leads_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"rep_verified_caller_ids","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"friendly_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_validation_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_caller_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"forward_to_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sms_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status_callback_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_recording_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"voicemail_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"voicemail_greeting","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"forward_sms_enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rep_caller_ids_one_default_per_user","definition":"CREATE UNIQUE INDEX idx_rep_caller_ids_one_default_per_user ON public.rep_verified_caller_ids USING btree (user_id) WHERE (is_default = true)"},{"name":"idx_rep_verified_caller_ids_tenant","definition":"CREATE INDEX idx_rep_verified_caller_ids_tenant ON public.rep_verified_caller_ids USING btree (tenant_org_id)"},{"name":"idx_rep_verified_caller_ids_user","definition":"CREATE INDEX idx_rep_verified_caller_ids_user ON public.rep_verified_caller_ids USING btree (user_id)"},{"name":"rep_verified_caller_ids_pkey","definition":"CREATE UNIQUE INDEX rep_verified_caller_ids_pkey ON public.rep_verified_caller_ids USING btree (id)"},{"name":"rep_verified_caller_ids_user_id_phone_number_key","definition":"CREATE UNIQUE INDEX rep_verified_caller_ids_user_id_phone_number_key ON public.rep_verified_caller_ids USING btree (user_id, phone_number)"}],"policies":[{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"rep_verified_caller_ids","permissive":"PERMISSIVE","policyname":"Tenant members view tenant caller IDs","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"rep_verified_caller_ids","permissive":"PERMISSIVE","policyname":"Users delete own caller IDs","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"rep_verified_caller_ids","permissive":"PERMISSIVE","policyname":"Users insert own caller IDs","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"rep_verified_caller_ids","permissive":"PERMISSIVE","policyname":"Users update own caller IDs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"rep_verified_caller_ids","permissive":"PERMISSIVE","policyname":"Users view own caller IDs","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_audit_forward_phone","definition":"CREATE TRIGGER trg_audit_forward_phone AFTER UPDATE OF forward_to_phone ON rep_verified_caller_ids FOR EACH ROW EXECUTE FUNCTION audit_phone_change()"},{"name":"trg_protect_forward_phone","definition":"CREATE TRIGGER trg_protect_forward_phone BEFORE INSERT OR UPDATE OF forward_to_phone ON rep_verified_caller_ids FOR EACH ROW EXECUTE FUNCTION protect_forward_phone()"},{"name":"trg_rep_verified_caller_ids_updated_at","definition":"CREATE TRIGGER trg_rep_verified_caller_ids_updated_at BEFORE UPDATE ON rep_verified_caller_ids FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"rep_verified_caller_ids_pkey","definition":"PRIMARY KEY (id)"},{"name":"rep_verified_caller_ids_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'verified'::text, 'failed'::text, 'expired'::text]))"},{"name":"rep_verified_caller_ids_user_id_phone_number_key","definition":"UNIQUE (user_id, phone_number)"}]},{"table":"repo_agent_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mode","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"http_status","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"ok","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"request_summary","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_repo_agent_audit_created","definition":"CREATE INDEX idx_repo_agent_audit_created ON public.repo_agent_audit USING btree (created_at DESC)"},{"name":"idx_repo_agent_audit_session","definition":"CREATE INDEX idx_repo_agent_audit_session ON public.repo_agent_audit USING btree (session_id)"},{"name":"repo_agent_audit_pkey","definition":"CREATE UNIQUE INDEX repo_agent_audit_pkey ON public.repo_agent_audit USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_repo_agent_admin()","roles":["authenticated"],"tablename":"repo_agent_audit","permissive":"PERMISSIVE","policyname":"repo_agent_audit_admin_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"false","roles":["authenticated"],"tablename":"repo_agent_audit","permissive":"PERMISSIVE","policyname":"repo_agent_audit_no_client_write","schemaname":"public","with_check":"false"}],"triggers":[],"constraints":[{"name":"repo_agent_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"repo_agent_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"mode","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"ended_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_repo_agent_sessions_expires","definition":"CREATE INDEX idx_repo_agent_sessions_expires ON public.repo_agent_sessions USING btree (expires_at)"},{"name":"idx_repo_agent_sessions_user","definition":"CREATE INDEX idx_repo_agent_sessions_user ON public.repo_agent_sessions USING btree (user_id)"},{"name":"repo_agent_sessions_pkey","definition":"CREATE UNIQUE INDEX repo_agent_sessions_pkey ON public.repo_agent_sessions USING btree (id)"},{"name":"repo_agent_sessions_token_hash_key","definition":"CREATE UNIQUE INDEX repo_agent_sessions_token_hash_key ON public.repo_agent_sessions USING btree (token_hash)"}],"policies":[{"cmd":"SELECT","qual":"is_repo_agent_admin()","roles":["authenticated"],"tablename":"repo_agent_sessions","permissive":"PERMISSIVE","policyname":"repo_agent_sessions_admin_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"false","roles":["authenticated"],"tablename":"repo_agent_sessions","permissive":"PERMISSIVE","policyname":"repo_agent_sessions_no_client_write","schemaname":"public","with_check":"false"}],"triggers":[],"constraints":[{"name":"repo_agent_sessions_mode_check","definition":"CHECK (mode = ANY (ARRAY['standard'::text, 'elevated'::text]))"},{"name":"repo_agent_sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"repo_agent_sessions_token_hash_key","definition":"UNIQUE (token_hash)"}]},{"table":"report_definitions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"character varying(255)","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"report_type","type":"character varying(50)","default":null,"identity":"","not_null":true,"generated":""},{"name":"config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"chart_config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_public","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"report_definitions_pkey","definition":"CREATE UNIQUE INDEX report_definitions_pkey ON public.report_definitions USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"report_definitions","permissive":"PERMISSIVE","policyname":"Users can manage reports","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"report_definitions","permissive":"PERMISSIVE","policyname":"Users can view own tenant reports","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"report_definitions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"revocation_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_normalized","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"trigger_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"matched_keyword","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_message_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_call_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"auto_suppressed","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_revocation_tenant_phone","definition":"CREATE INDEX idx_revocation_tenant_phone ON public.revocation_events USING btree (tenant_org_id, phone_normalized, created_at DESC)"},{"name":"revocation_events_pkey","definition":"CREATE UNIQUE INDEX revocation_events_pkey ON public.revocation_events USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"revocation_events","permissive":"PERMISSIVE","policyname":"tenant_members_insert_revocation","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"revocation_events","permissive":"PERMISSIVE","policyname":"tenant_members_view_revocation","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_revocation_to_dnc","definition":"CREATE TRIGGER trg_revocation_to_dnc AFTER INSERT ON revocation_events FOR EACH ROW EXECUTE FUNCTION apply_revocation_to_dnc()"}],"constraints":[{"name":"revocation_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ring_group_members","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"ring_group_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"priority","type":"smallint","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_ring_group_members_user","definition":"CREATE INDEX idx_ring_group_members_user ON public.ring_group_members USING btree (user_id)"},{"name":"ring_group_members_pkey","definition":"CREATE UNIQUE INDEX ring_group_members_pkey ON public.ring_group_members USING btree (id)"},{"name":"uq_ring_group_member","definition":"CREATE UNIQUE INDEX uq_ring_group_member ON public.ring_group_members USING btree (ring_group_id, user_id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ring_group_members","permissive":"PERMISSIVE","policyname":"ring_group_members_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ring_group_members","permissive":"PERMISSIVE","policyname":"ring_group_members_write_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"}],"triggers":[],"constraints":[{"name":"ring_group_members_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"ring_groups","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"strategy","type":"text","default":"'round_robin'::text","identity":"","not_null":true,"generated":""},{"name":"ring_seconds_per_leg","type":"smallint","default":"15","identity":"","not_null":true,"generated":""},{"name":"max_wait_seconds","type":"smallint","default":"90","identity":"","not_null":true,"generated":""},{"name":"hold_music_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"overflow_action","type":"text","default":"'callback'::text","identity":"","not_null":true,"generated":""},{"name":"overflow_target_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_rung_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_ring_groups_tenant","definition":"CREATE INDEX idx_ring_groups_tenant ON public.ring_groups USING btree (tenant_org_id)"},{"name":"ring_groups_pkey","definition":"CREATE UNIQUE INDEX ring_groups_pkey ON public.ring_groups USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ring_groups","permissive":"PERMISSIVE","policyname":"ring_groups_select_tenant_members","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"ring_groups","permissive":"PERMISSIVE","policyname":"ring_groups_write_managers","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_ring_groups_updated_at","definition":"CREATE TRIGGER trg_ring_groups_updated_at BEFORE UPDATE ON ring_groups FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"ring_groups_overflow_action_check","definition":"CHECK (overflow_action = ANY (ARRAY['callback'::text, 'voicemail'::text, 'hangup'::text, 'ring_group'::text]))"},{"name":"ring_groups_pkey","definition":"PRIMARY KEY (id)"},{"name":"ring_groups_strategy_check","definition":"CHECK (strategy = ANY (ARRAY['simultaneous'::text, 'round_robin'::text, 'longest_idle'::text]))"}]},{"table":"rls_policy_changes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"changed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"table_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"policy_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"operation","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"old_definition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_definition","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"rls_policy_changes_pkey","definition":"CREATE UNIQUE INDEX rls_policy_changes_pkey ON public.rls_policy_changes USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"rls_policy_changes","permissive":"PERMISSIVE","policyname":"platform_admin_manage_rls_changes","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"rls_policy_changes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"role_permissions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"permission_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"role_permissions_pkey","definition":"CREATE UNIQUE INDEX role_permissions_pkey ON public.role_permissions USING btree (id)"},{"name":"role_permissions_role_permission_key_tenant_id_key","definition":"CREATE UNIQUE INDEX role_permissions_role_permission_key_tenant_id_key ON public.role_permissions USING btree (role, permission_key, tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"true","roles":["authenticated"],"tablename":"role_permissions","permissive":"PERMISSIVE","policyname":"Role permissions viewable by authenticated users","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"role_permissions_pkey","definition":"PRIMARY KEY (id)"},{"name":"role_permissions_role_permission_key_tenant_id_key","definition":"UNIQUE (role, permission_key, tenant_id)"}]},{"table":"roof_estimate_reports","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"report_type","type":"text","default":"'measurement'::text","identity":"","not_null":false,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":false,"generated":""},{"name":"pdf_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pdf_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"file_size_bytes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"generated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"generated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"report_data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_roof_estimate_reports_estimate","definition":"CREATE INDEX idx_roof_estimate_reports_estimate ON public.roof_estimate_reports USING btree (estimate_id)"},{"name":"idx_roof_estimate_reports_tenant","definition":"CREATE INDEX idx_roof_estimate_reports_tenant ON public.roof_estimate_reports USING btree (tenant_org_id)"},{"name":"roof_estimate_reports_pkey","definition":"CREATE UNIQUE INDEX roof_estimate_reports_pkey ON public.roof_estimate_reports USING btree (id)"},{"name":"unique_estimate_version","definition":"CREATE UNIQUE INDEX unique_estimate_version ON public.roof_estimate_reports USING btree (estimate_id, version)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roof_estimate_reports","permissive":"PERMISSIVE","policyname":"Users create reports","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"roof_estimate_reports","permissive":"PERMISSIVE","policyname":"Users view tenant reports","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"roof_estimate_reports_pkey","definition":"PRIMARY KEY (id)"},{"name":"unique_estimate_version","definition":"UNIQUE (estimate_id, version)"}]},{"table":"roof_estimate_versions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"version_number","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"snapshot","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"changed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"change_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_estimate_versions_estimate","definition":"CREATE INDEX idx_estimate_versions_estimate ON public.roof_estimate_versions USING btree (estimate_id)"},{"name":"roof_estimate_versions_estimate_id_version_number_key","definition":"CREATE UNIQUE INDEX roof_estimate_versions_estimate_id_version_number_key ON public.roof_estimate_versions USING btree (estimate_id, version_number)"},{"name":"roof_estimate_versions_pkey","definition":"CREATE UNIQUE INDEX roof_estimate_versions_pkey ON public.roof_estimate_versions USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roof_estimate_versions","permissive":"PERMISSIVE","policyname":"Tenant members insert estimate versions","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM roof_estimates re\n  WHERE ((re.id = roof_estimate_versions.estimate_id) AND is_tenant_member(re.tenant_org_id))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM roof_estimates re\n  WHERE ((re.id = roof_estimate_versions.estimate_id) AND is_tenant_member(re.tenant_org_id))))","roles":["public"],"tablename":"roof_estimate_versions","permissive":"PERMISSIVE","policyname":"Tenant members view estimate versions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"roof_estimate_versions_estimate_id_version_number_key","definition":"UNIQUE (estimate_id, version_number)"},{"name":"roof_estimate_versions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"roof_estimates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"total_squares","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"pitch","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pitch_degrees","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"layers","type":"integer","default":"1","identity":"","not_null":false,"generated":""},{"name":"waste_factor","type":"numeric","default":"10","identity":"","not_null":false,"generated":""},{"name":"material_cost_total","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"labor_cost_total","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"dump_fees","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"permits_fees","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"other_costs","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"subtotal","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"margin_pct","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"tax_pct","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"total_job_price","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"line_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"polygon_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"calculation_metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"facet_count","type":"integer","default":"1","identity":"","not_null":false,"generated":""},{"name":"predominant_pitch","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pitched_area_sqft","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"flat_area_sqft","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"linear_measurements","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"facet_details","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"aerial_image_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"report_pdf_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"report_pdf_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"squares","type":"numeric","default":"round((total_squares * ((1)::numeric + (COALESCE(waste_factor, (10)::numeric) / (100)::numeric))), 1)","identity":"","not_null":false,"generated":"s"},{"name":"total_sqft","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"pitch_ratio","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"overhead_pct","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"commission_pct","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"pricing_mode","type":"text","default":"'retail'::text","identity":"","not_null":false,"generated":""},{"name":"approval_status","type":"text","default":"'draft'::text","identity":"","not_null":false,"generated":""},{"name":"approved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rejection_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_roof_estimates_approval","definition":"CREATE INDEX idx_roof_estimates_approval ON public.roof_estimates USING btree (approval_status)"},{"name":"idx_roof_estimates_report","definition":"CREATE INDEX idx_roof_estimates_report ON public.roof_estimates USING btree (report_pdf_path) WHERE (report_pdf_path IS NOT NULL)"},{"name":"idx_roof_estimates_tenant_contact_updated","definition":"CREATE INDEX idx_roof_estimates_tenant_contact_updated ON public.roof_estimates USING btree (tenant_org_id, contact_id, updated_at DESC)"},{"name":"roof_estimates_pkey","definition":"CREATE UNIQUE INDEX roof_estimates_pkey ON public.roof_estimates USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"roof_estimates","permissive":"PERMISSIVE","policyname":"re_all","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (roof_estimates.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"roof_estimates","permissive":"PERMISSIVE","policyname":"tenant_users_delete_roof_estimates","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"roof_estimates","permissive":"PERMISSIVE","policyname":"tenant_users_insert_roof_estimates","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (roof_estimates.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (roof_estimates.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"roof_estimates","permissive":"PERMISSIVE","policyname":"tenant_users_update_roof_estimates","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (roof_estimates.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (roof_estimates.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"roof_estimates","permissive":"PERMISSIVE","policyname":"tenant_users_view_roof_estimates","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"roof_estimates_pkey","definition":"PRIMARY KEY (id)"},{"name":"roof_estimates_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'sent'::text, 'approved'::text, 'rejected'::text]))"}]},{"table":"roof_help_funnel_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"session_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"landing_path","type":"text","default":"'/'::text","identity":"","not_null":true,"generated":""},{"name":"market_slug","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_slug","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_medium","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_campaign","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_content","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"acquisition_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer_host","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"visitor_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"proof_internal","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roof_help_funnel_events_pkey","definition":"CREATE UNIQUE INDEX roof_help_funnel_events_pkey ON public.roof_help_funnel_events USING btree (id)"},{"name":"roof_help_funnel_events_session_event_landing_key","definition":"CREATE UNIQUE INDEX roof_help_funnel_events_session_event_landing_key ON public.roof_help_funnel_events USING btree (session_id, event_name, landing_path)"},{"name":"roof_help_funnel_events_tenant_event_occurred_idx","definition":"CREATE INDEX roof_help_funnel_events_tenant_event_occurred_idx ON public.roof_help_funnel_events USING btree (tenant_org_id, event_name, occurred_at DESC)"},{"name":"roof_help_funnel_events_tenant_occurred_idx","definition":"CREATE INDEX roof_help_funnel_events_tenant_occurred_idx ON public.roof_help_funnel_events USING btree (tenant_org_id, occurred_at DESC)"},{"name":"roof_help_funnel_events_visitor_hash_created_idx","definition":"CREATE INDEX roof_help_funnel_events_visitor_hash_created_idx ON public.roof_help_funnel_events USING btree (visitor_hash, created_at DESC) WHERE (visitor_hash IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin() OR is_tenant_member(tenant_org_id))","roles":["authenticated"],"tablename":"roof_help_funnel_events","permissive":"PERMISSIVE","policyname":"Roof Help Finder members can view funnel events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"roof_help_funnel_events_event_name_check","definition":"CHECK (event_name = ANY (ARRAY['page_view'::text, 'roof_help_cta_open'::text, 'form_started'::text, 'address_verified'::text, 'submit_attempt'::text, 'submit_success'::text, 'submit_error'::text]))"},{"name":"roof_help_funnel_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"roof_help_funnel_events_session_event_landing_key","definition":"UNIQUE (session_id, event_name, landing_path)"}]},{"table":"roof_measurement_jobs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"requested_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"stage","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"progress","type":"integer","default":"5","identity":"","not_null":true,"generated":""},{"name":"request_payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"result","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"return_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempt_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"roof_measurement_jobs_pkey","definition":"CREATE UNIQUE INDEX roof_measurement_jobs_pkey ON public.roof_measurement_jobs USING btree (id)"},{"name":"roof_measurement_jobs_requester_status_idx","definition":"CREATE INDEX roof_measurement_jobs_requester_status_idx ON public.roof_measurement_jobs USING btree (requested_by, status, updated_at DESC)"},{"name":"roof_measurement_jobs_tenant_updated_idx","definition":"CREATE INDEX roof_measurement_jobs_tenant_updated_idx ON public.roof_measurement_jobs USING btree (tenant_org_id, updated_at DESC)"}],"policies":[],"triggers":[],"constraints":[{"name":"roof_measurement_jobs_pkey","definition":"PRIMARY KEY (id)"},{"name":"roof_measurement_jobs_progress_check","definition":"CHECK (progress >= 0 AND progress <= 100)"},{"name":"roof_measurement_jobs_requested_by_fkey","definition":"FOREIGN KEY (requested_by) REFERENCES users(id) ON DELETE CASCADE"},{"name":"roof_measurement_jobs_status_check","definition":"CHECK (status = ANY (ARRAY['queued'::text, 'running'::text, 'complete'::text, 'failed'::text]))"},{"name":"roof_measurement_jobs_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"roof_price_book","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"item_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'material'::text","identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"unit","type":"text","default":"'SQ'::text","identity":"","not_null":true,"generated":""},{"name":"unit_price","type":"numeric","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_roof_price_book_tenant","definition":"CREATE INDEX idx_roof_price_book_tenant ON public.roof_price_book USING btree (tenant_org_id)"},{"name":"roof_price_book_pkey","definition":"CREATE UNIQUE INDEX roof_price_book_pkey ON public.roof_price_book USING btree (id)"},{"name":"roof_price_book_tenant_org_id_item_code_key","definition":"CREATE UNIQUE INDEX roof_price_book_tenant_org_id_item_code_key ON public.roof_price_book USING btree (tenant_org_id, item_code)"}],"policies":[{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"roof_price_book","permissive":"PERMISSIVE","policyname":"Users delete tenant price book","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roof_price_book","permissive":"PERMISSIVE","policyname":"Users manage tenant price book","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"roof_price_book","permissive":"PERMISSIVE","policyname":"Users update tenant price book","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"roof_price_book","permissive":"PERMISSIVE","policyname":"Users view tenant price book","schemaname":"public","with_check":null}],"triggers":[{"name":"roof_price_book_updated_at","definition":"CREATE TRIGGER roof_price_book_updated_at BEFORE UPDATE ON roof_price_book FOR EACH ROW EXECUTE FUNCTION update_roof_price_book_updated_at()"}],"constraints":[{"name":"roof_price_book_pkey","definition":"PRIMARY KEY (id)"},{"name":"roof_price_book_tenant_org_id_item_code_key","definition":"UNIQUE (tenant_org_id, item_code)"}]},{"table":"roof_price_book_items","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"item_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'material'::text","identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"unit","type":"text","default":"'SQ'::text","identity":"","not_null":true,"generated":""},{"name":"unit_price","type":"numeric","default":"0","identity":"","not_null":true,"generated":""},{"name":"sort_order","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"roof_type","type":"text","default":"'shingle'::text","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_price_book_roof_type","definition":"CREATE INDEX idx_price_book_roof_type ON public.roof_price_book_items USING btree (roof_type)"},{"name":"idx_price_book_tenant","definition":"CREATE INDEX idx_price_book_tenant ON public.roof_price_book_items USING btree (tenant_org_id)"},{"name":"roof_price_book_items_pkey","definition":"CREATE UNIQUE INDEX roof_price_book_items_pkey ON public.roof_price_book_items USING btree (id)"},{"name":"roof_price_book_items_tenant_org_id_item_code_roof_type_key","definition":"CREATE UNIQUE INDEX roof_price_book_items_tenant_org_id_item_code_roof_type_key ON public.roof_price_book_items USING btree (tenant_org_id, item_code, roof_type)"}],"policies":[{"cmd":"DELETE","qual":"is_tenant_member(tenant_org_id)","roles":["public"],"tablename":"roof_price_book_items","permissive":"PERMISSIVE","policyname":"Tenant members delete price book","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roof_price_book_items","permissive":"PERMISSIVE","policyname":"Tenant members insert price book","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["public"],"tablename":"roof_price_book_items","permissive":"PERMISSIVE","policyname":"Tenant members update price book","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["public"],"tablename":"roof_price_book_items","permissive":"PERMISSIVE","policyname":"Tenant members view price book","schemaname":"public","with_check":null}],"triggers":[{"name":"roof_price_book_updated_at","definition":"CREATE TRIGGER roof_price_book_updated_at BEFORE UPDATE ON roof_price_book_items FOR EACH ROW EXECUTE FUNCTION update_roof_price_book_updated_at()"}],"constraints":[{"name":"roof_price_book_items_pkey","definition":"PRIMARY KEY (id)"},{"name":"roof_price_book_items_tenant_org_id_item_code_roof_type_key","definition":"UNIQUE (tenant_org_id, item_code, roof_type)"}]},{"table":"roofing_closeout","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"final_photos_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"completion_certificate_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"completion_certificate_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"warranty_registered","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"warranty_provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"warranty_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"final_invoice_sent","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"final_payment_received","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"lien_release_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"review_requested","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"review_completed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"referral_requested","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"referral_received","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"homeowner_handoff_complete","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"closed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_closeout_job_id_key","definition":"CREATE UNIQUE INDEX roofing_closeout_job_id_key ON public.roofing_closeout USING btree (job_id)"},{"name":"roofing_closeout_pkey","definition":"CREATE UNIQUE INDEX roofing_closeout_pkey ON public.roofing_closeout USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_closeout","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_closeout","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_closeout","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_closeout","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[{"name":"roofing_ops_touch_updated_at","definition":"CREATE TRIGGER roofing_ops_touch_updated_at BEFORE UPDATE ON roofing_closeout FOR EACH ROW EXECUTE FUNCTION roofing_ops_touch_updated_at()"}],"constraints":[{"name":"roofing_closeout_job_id_fkey","definition":"FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE"},{"name":"roofing_closeout_job_id_key","definition":"UNIQUE (job_id)"},{"name":"roofing_closeout_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_closeout_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"roofing_commissions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"payee_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"basis_amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"rate_pct","type":"numeric(7,3)","default":"0","identity":"","not_null":true,"generated":""},{"name":"amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'projected'::text","identity":"","not_null":true,"generated":""},{"name":"earned_at","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_commissions_job_idx","definition":"CREATE INDEX roofing_commissions_job_idx ON public.roofing_commissions USING btree (tenant_id, job_id, created_at DESC)"},{"name":"roofing_commissions_pkey","definition":"CREATE UNIQUE INDEX roofing_commissions_pkey ON public.roofing_commissions USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_commissions","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_commissions","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_commissions","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_commissions","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[{"name":"roofing_ops_touch_updated_at","definition":"CREATE TRIGGER roofing_ops_touch_updated_at BEFORE UPDATE ON roofing_commissions FOR EACH ROW EXECUTE FUNCTION roofing_ops_touch_updated_at()"}],"constraints":[{"name":"roofing_commissions_job_id_fkey","definition":"FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE"},{"name":"roofing_commissions_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_commissions_status_check","definition":"CHECK (status = ANY (ARRAY['projected'::text, 'earned'::text, 'approved'::text, 'payable'::text, 'paid'::text, 'void'::text]))"},{"name":"roofing_commissions_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"roofing_cost_entries","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"cost_type","type":"text","default":"'actual'::text","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"vendor","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reference","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"incurred_on","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_cost_entries_job_idx","definition":"CREATE INDEX roofing_cost_entries_job_idx ON public.roofing_cost_entries USING btree (tenant_id, job_id, created_at DESC)"},{"name":"roofing_cost_entries_pkey","definition":"CREATE UNIQUE INDEX roofing_cost_entries_pkey ON public.roofing_cost_entries USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_cost_entries","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_cost_entries","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_cost_entries","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_cost_entries","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[],"constraints":[{"name":"roofing_cost_entries_category_check","definition":"CHECK (category = ANY (ARRAY['materials'::text, 'labor'::text, 'subcontractor'::text, 'permit'::text, 'dump'::text, 'equipment'::text, 'commission'::text, 'financing_fee'::text, 'other'::text]))"},{"name":"roofing_cost_entries_cost_type_check","definition":"CHECK (cost_type = ANY (ARRAY['estimated'::text, 'committed'::text, 'actual'::text]))"},{"name":"roofing_cost_entries_job_id_fkey","definition":"FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE"},{"name":"roofing_cost_entries_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_cost_entries_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"roofing_insurance_financials","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"acv","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"rcv","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"deductible","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"depreciation_withheld","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"depreciation_recovered","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"carrier_payment_received","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"mortgage_check_amount","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"mortgage_check_status","type":"text","default":"'not_applicable'::text","identity":"","not_null":true,"generated":""},{"name":"customer_out_of_pocket","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_insurance_financials_job_id_key","definition":"CREATE UNIQUE INDEX roofing_insurance_financials_job_id_key ON public.roofing_insurance_financials USING btree (job_id)"},{"name":"roofing_insurance_financials_pkey","definition":"CREATE UNIQUE INDEX roofing_insurance_financials_pkey ON public.roofing_insurance_financials USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_insurance_financials","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_insurance_financials","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_insurance_financials","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_insurance_financials","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[{"name":"roofing_ops_touch_updated_at","definition":"CREATE TRIGGER roofing_ops_touch_updated_at BEFORE UPDATE ON roofing_insurance_financials FOR EACH ROW EXECUTE FUNCTION roofing_ops_touch_updated_at()"}],"constraints":[{"name":"roofing_insurance_financials_job_id_fkey","definition":"FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE"},{"name":"roofing_insurance_financials_job_id_key","definition":"UNIQUE (job_id)"},{"name":"roofing_insurance_financials_mortgage_check_status_check","definition":"CHECK (mortgage_check_status = ANY (ARRAY['not_applicable'::text, 'not_received'::text, 'received'::text, 'endorsement_needed'::text, 'sent_for_endorsement'::text, 'returned'::text, 'deposited'::text, 'blocked'::text]))"},{"name":"roofing_insurance_financials_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_insurance_financials_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"roofing_material_orders","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"supplier_provider","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""},{"name":"supplier_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"supplier_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"supplier_branch","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":true,"generated":""},{"name":"delivery_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"subtotal","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"tax","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"total","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"line_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"external_order_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ordered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"delivered_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_material_orders_job_idx","definition":"CREATE INDEX roofing_material_orders_job_idx ON public.roofing_material_orders USING btree (tenant_id, job_id, created_at DESC)"},{"name":"roofing_material_orders_pkey","definition":"CREATE UNIQUE INDEX roofing_material_orders_pkey ON public.roofing_material_orders USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_material_orders","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_material_orders","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_material_orders","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_material_orders","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[{"name":"roofing_ops_touch_updated_at","definition":"CREATE TRIGGER roofing_ops_touch_updated_at BEFORE UPDATE ON roofing_material_orders FOR EACH ROW EXECUTE FUNCTION roofing_ops_touch_updated_at()"}],"constraints":[{"name":"roofing_material_orders_job_id_fkey","definition":"FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE"},{"name":"roofing_material_orders_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_material_orders_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'ordered'::text, 'confirmed'::text, 'scheduled'::text, 'delivered'::text, 'shortage'::text, 'returned'::text, 'cancelled'::text, 'blocked'::text]))"},{"name":"roofing_material_orders_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"roofing_project_ops","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"job_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimate_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"project_phase","type":"text","default":"'preproduction'::text","identity":"","not_null":true,"generated":""},{"name":"funding_type","type":"text","default":"'retail'::text","identity":"","not_null":true,"generated":""},{"name":"contract_total","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"deposit_required","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"deposit_collected","type":"numeric(14,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"install_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"weather_hold","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"production_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"measurement_status","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"materials_status","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"permit_status","type":"text","default":"'not_checked'::text","identity":"","not_null":true,"generated":""},{"name":"insurance_status","type":"text","default":"'not_applicable'::text","identity":"","not_null":true,"generated":""},{"name":"financing_status","type":"text","default":"'not_applicable'::text","identity":"","not_null":true,"generated":""},{"name":"closeout_status","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"warranty_status","type":"text","default":"'not_started'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_project_ops_install_idx","definition":"CREATE INDEX roofing_project_ops_install_idx ON public.roofing_project_ops USING btree (tenant_id, install_date)"},{"name":"roofing_project_ops_job_id_key","definition":"CREATE UNIQUE INDEX roofing_project_ops_job_id_key ON public.roofing_project_ops USING btree (job_id)"},{"name":"roofing_project_ops_pkey","definition":"CREATE UNIQUE INDEX roofing_project_ops_pkey ON public.roofing_project_ops USING btree (id)"},{"name":"roofing_project_ops_tenant_idx","definition":"CREATE INDEX roofing_project_ops_tenant_idx ON public.roofing_project_ops USING btree (tenant_id)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_project_ops","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_project_ops","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_project_ops","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_project_ops","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[{"name":"roofing_ops_touch_updated_at","definition":"CREATE TRIGGER roofing_ops_touch_updated_at BEFORE UPDATE ON roofing_project_ops FOR EACH ROW EXECUTE FUNCTION roofing_ops_touch_updated_at()"}],"constraints":[{"name":"roofing_project_ops_closeout_status_check","definition":"CHECK (closeout_status = ANY (ARRAY['not_started'::text, 'in_progress'::text, 'ready'::text, 'complete'::text, 'blocked'::text]))"},{"name":"roofing_project_ops_financing_status_check","definition":"CHECK (financing_status = ANY (ARRAY['not_applicable'::text, 'draft'::text, 'submitted'::text, 'approved'::text, 'declined'::text, 'funded'::text]))"},{"name":"roofing_project_ops_funding_type_check","definition":"CHECK (funding_type = ANY (ARRAY['retail'::text, 'insurance'::text]))"},{"name":"roofing_project_ops_insurance_status_check","definition":"CHECK (insurance_status = ANY (ARRAY['not_applicable'::text, 'intake'::text, 'carrier_review'::text, 'supplement_followup'::text, 'payment_pending'::text, 'mortgage_hold'::text, 'ready'::text, 'blocked'::text]))"},{"name":"roofing_project_ops_job_id_fkey","definition":"FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE"},{"name":"roofing_project_ops_job_id_key","definition":"UNIQUE (job_id)"},{"name":"roofing_project_ops_materials_status_check","definition":"CHECK (materials_status = ANY (ARRAY['not_started'::text, 'draft'::text, 'ordered'::text, 'confirmed'::text, 'scheduled'::text, 'delivered'::text, 'shortage'::text, 'returned'::text, 'blocked'::text]))"},{"name":"roofing_project_ops_measurement_status_check","definition":"CHECK (measurement_status = ANY (ARRAY['not_started'::text, 'ordered'::text, 'processing'::text, 'ready'::text, 'failed'::text]))"},{"name":"roofing_project_ops_permit_status_check","definition":"CHECK (permit_status = ANY (ARRAY['not_checked'::text, 'not_required'::text, 'required'::text, 'applied'::text, 'issued'::text, 'inspection_pending'::text, 'finaled'::text, 'expired'::text, 'denied'::text, 'unknown'::text]))"},{"name":"roofing_project_ops_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_project_ops_project_phase_check","definition":"CHECK (project_phase = ANY (ARRAY['inspection'::text, 'estimating'::text, 'proposal'::text, 'contract'::text, 'preproduction'::text, 'scheduled'::text, 'production'::text, 'closeout'::text, 'complete'::text, 'lost'::text]))"},{"name":"roofing_project_ops_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"roofing_project_ops_warranty_status_check","definition":"CHECK (warranty_status = ANY (ARRAY['not_started'::text, 'pending_registration'::text, 'registered'::text, 'not_applicable'::text]))"}]},{"table":"roofing_provider_connections","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_category","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'disconnected'::text","identity":"","not_null":true,"generated":""},{"name":"external_account_label","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"capabilities","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"last_verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_sync_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"roofing_provider_connections_pkey","definition":"CREATE UNIQUE INDEX roofing_provider_connections_pkey ON public.roofing_provider_connections USING btree (id)"},{"name":"roofing_provider_connections_tenant_id_provider_category_pr_key","definition":"CREATE UNIQUE INDEX roofing_provider_connections_tenant_id_provider_category_pr_key ON public.roofing_provider_connections USING btree (tenant_id, provider_category, provider_code)"}],"policies":[{"cmd":"DELETE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_provider_connections","permissive":"PERMISSIVE","policyname":"roofing_ops_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"roofing_provider_connections","permissive":"PERMISSIVE","policyname":"roofing_ops_insert","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"},{"cmd":"SELECT","qual":"roofing_ops_can_read(tenant_id)","roles":["public"],"tablename":"roofing_provider_connections","permissive":"PERMISSIVE","policyname":"roofing_ops_read","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"roofing_ops_can_manage(tenant_id)","roles":["public"],"tablename":"roofing_provider_connections","permissive":"PERMISSIVE","policyname":"roofing_ops_update","schemaname":"public","with_check":"roofing_ops_can_manage(tenant_id)"}],"triggers":[{"name":"roofing_ops_touch_updated_at","definition":"CREATE TRIGGER roofing_ops_touch_updated_at BEFORE UPDATE ON roofing_provider_connections FOR EACH ROW EXECUTE FUNCTION roofing_ops_touch_updated_at()"}],"constraints":[{"name":"roofing_provider_connections_pkey","definition":"PRIMARY KEY (id)"},{"name":"roofing_provider_connections_provider_category_check","definition":"CHECK (provider_category = ANY (ARRAY['measurement'::text, 'supplier'::text, 'accounting'::text, 'financing'::text, 'payments'::text, 'photos'::text]))"},{"name":"roofing_provider_connections_status_check","definition":"CHECK (status = ANY (ARRAY['disconnected'::text, 'action_required'::text, 'connected'::text, 'degraded'::text, 'disabled'::text]))"},{"name":"roofing_provider_connections_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"roofing_provider_connections_tenant_id_provider_category_pr_key","definition":"UNIQUE (tenant_id, provider_category, provider_code)"}]},{"table":"route_configs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"routes","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_route_configs_active","definition":"CREATE INDEX idx_route_configs_active ON public.route_configs USING btree (is_active)"},{"name":"idx_route_configs_role","definition":"CREATE INDEX idx_route_configs_role ON public.route_configs USING btree (role)"},{"name":"route_configs_pkey","definition":"CREATE UNIQUE INDEX route_configs_pkey ON public.route_configs USING btree (id)"},{"name":"route_configs_role_key","definition":"CREATE UNIQUE INDEX route_configs_role_key ON public.route_configs USING btree (role)"}],"policies":[{"cmd":"SELECT","qual":"(is_active = true)","roles":["authenticated"],"tablename":"route_configs","permissive":"PERMISSIVE","policyname":"Authenticated users can view active route configs","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"route_configs","permissive":"PERMISSIVE","policyname":"platform_admin_manage_route_configs","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"route_configs_pkey","definition":"PRIMARY KEY (id)"},{"name":"route_configs_role_key","definition":"UNIQUE (role)"}]},{"table":"route_session_stops","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"route_session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"door_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"stop_order","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"arrived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_rss_door","definition":"CREATE INDEX idx_rss_door ON public.route_session_stops USING btree (door_id)"},{"name":"idx_rss_session","definition":"CREATE INDEX idx_rss_session ON public.route_session_stops USING btree (route_session_id, stop_order)"},{"name":"route_session_stops_pkey","definition":"CREATE UNIQUE INDEX route_session_stops_pkey ON public.route_session_stops USING btree (id)"},{"name":"route_session_stops_route_session_id_stop_order_key","definition":"CREATE UNIQUE INDEX route_session_stops_route_session_id_stop_order_key ON public.route_session_stops USING btree (route_session_id, stop_order)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"route_session_stops","permissive":"PERMISSIVE","policyname":"rss_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) AND (EXISTS ( SELECT 1\n   FROM route_sessions rs\n  WHERE ((rs.id = route_session_stops.route_session_id) AND (rs.user_id = uid())))))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) AND (EXISTS ( SELECT 1\n   FROM route_sessions rs\n  WHERE ((rs.id = route_session_stops.route_session_id) AND ((rs.user_id = uid()) OR is_manager_or_higher(uid(), rs.tenant_org_id) OR is_system_admin(uid()))))))","roles":["authenticated"],"tablename":"route_session_stops","permissive":"PERMISSIVE","policyname":"rss_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_org_id) AND (EXISTS ( SELECT 1\n   FROM route_sessions rs\n  WHERE ((rs.id = route_session_stops.route_session_id) AND ((rs.user_id = uid()) OR is_system_admin(uid()))))))","roles":["authenticated"],"tablename":"route_session_stops","permissive":"PERMISSIVE","policyname":"rss_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_rss_updated","definition":"CREATE TRIGGER trg_rss_updated BEFORE UPDATE ON route_session_stops FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"route_session_stops_pkey","definition":"PRIMARY KEY (id)"},{"name":"route_session_stops_route_session_id_stop_order_key","definition":"UNIQUE (route_session_id, stop_order)"}]},{"table":"route_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"total_doors","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"doors_completed","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"estimated_minutes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"total_distance_meters","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"start_lat","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"start_lng","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"ended_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_route_sessions_active","definition":"CREATE INDEX idx_route_sessions_active ON public.route_sessions USING btree (tenant_org_id, status) WHERE (status = 'active'::text)"},{"name":"idx_route_sessions_tenant_user","definition":"CREATE INDEX idx_route_sessions_tenant_user ON public.route_sessions USING btree (tenant_org_id, user_id, started_at DESC)"},{"name":"route_sessions_pkey","definition":"CREATE UNIQUE INDEX route_sessions_pkey ON public.route_sessions USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"route_sessions","permissive":"PERMISSIVE","policyname":"rs_insert","schemaname":"public","with_check":"(is_tenant_member(uid(), tenant_org_id) AND (user_id = uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_org_id) AND ((user_id = uid()) OR is_manager_or_higher(uid(), tenant_org_id) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"route_sessions","permissive":"PERMISSIVE","policyname":"rs_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(uid(), tenant_org_id) AND ((user_id = uid()) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"route_sessions","permissive":"PERMISSIVE","policyname":"rs_update","schemaname":"public","with_check":"is_tenant_member(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_route_sessions_updated","definition":"CREATE TRIGGER trg_route_sessions_updated BEFORE UPDATE ON route_sessions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"route_sessions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"scheduled_callbacks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"promised_to_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"due_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_scheduled_callbacks_contact","definition":"CREATE INDEX idx_scheduled_callbacks_contact ON public.scheduled_callbacks USING btree (contact_id)"},{"name":"idx_scheduled_callbacks_due","definition":"CREATE INDEX idx_scheduled_callbacks_due ON public.scheduled_callbacks USING btree (tenant_org_id, status, due_at)"},{"name":"scheduled_callbacks_pkey","definition":"CREATE UNIQUE INDEX scheduled_callbacks_pkey ON public.scheduled_callbacks USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"(is_system_admin(uid()) OR is_tenant_member(tenant_org_id))","roles":["authenticated"],"tablename":"scheduled_callbacks","permissive":"PERMISSIVE","policyname":"system admins can delete scheduled callbacks","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"scheduled_callbacks","permissive":"PERMISSIVE","policyname":"tenant members can insert scheduled callbacks","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"scheduled_callbacks","permissive":"PERMISSIVE","policyname":"tenant members can update scheduled callbacks","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"scheduled_callbacks","permissive":"PERMISSIVE","policyname":"tenant members can view scheduled callbacks","schemaname":"public","with_check":null}],"triggers":[{"name":"scheduled_callbacks_set_updated_at","definition":"CREATE TRIGGER scheduled_callbacks_set_updated_at BEFORE UPDATE ON scheduled_callbacks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"scheduled_callbacks_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"scheduled_emails","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scheduled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_scheduled_emails_status","definition":"CREATE INDEX idx_scheduled_emails_status ON public.scheduled_emails USING btree (status, scheduled_at)"},{"name":"scheduled_emails_pkey","definition":"CREATE UNIQUE INDEX scheduled_emails_pkey ON public.scheduled_emails USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"scheduled_emails","permissive":"PERMISSIVE","policyname":"Tenant isolation for scheduled_emails","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"scheduled_emails_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"scheduled_emails_pkey","definition":"PRIMARY KEY (id)"},{"name":"scheduled_emails_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'sending'::text, 'sent'::text, 'failed'::text, 'cancelled'::text]))"}]},{"table":"scheduled_reports","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"report_definition_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"character varying(255)","default":null,"identity":"","not_null":true,"generated":""},{"name":"schedule_type","type":"character varying(20)","default":null,"identity":"","not_null":true,"generated":""},{"name":"schedule_config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"recipients","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"format","type":"character varying(20)","default":"'pdf'::character varying","identity":"","not_null":false,"generated":""},{"name":"last_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_run_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"scheduled_reports_pkey","definition":"CREATE UNIQUE INDEX scheduled_reports_pkey ON public.scheduled_reports USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"scheduled_reports","permissive":"PERMISSIVE","policyname":"Users can manage scheduled reports","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"scheduled_reports","permissive":"PERMISSIVE","policyname":"Users can view own tenant scheduled reports","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"scheduled_reports_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"scheduled_sms","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"scheduled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_scheduled_sms_status","definition":"CREATE INDEX idx_scheduled_sms_status ON public.scheduled_sms USING btree (status, scheduled_at)"},{"name":"scheduled_sms_pkey","definition":"CREATE UNIQUE INDEX scheduled_sms_pkey ON public.scheduled_sms USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"scheduled_sms","permissive":"PERMISSIVE","policyname":"Tenant isolation for scheduled_sms","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"scheduled_sms_pkey","definition":"PRIMARY KEY (id)"},{"name":"scheduled_sms_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'sending'::text, 'sent'::text, 'failed'::text, 'cancelled'::text]))"}]},{"table":"score_audit_log","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"score_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"subject_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"previous_value","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_value","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_score_audit_event_type","definition":"CREATE INDEX idx_score_audit_event_type ON public.score_audit_log USING btree (event_type, created_at DESC)"},{"name":"idx_score_audit_subject","definition":"CREATE INDEX idx_score_audit_subject ON public.score_audit_log USING btree (subject_type, subject_id, created_at DESC)"},{"name":"idx_score_audit_tenant_time","definition":"CREATE INDEX idx_score_audit_tenant_time ON public.score_audit_log USING btree (tenant_org_id, created_at DESC)"},{"name":"score_audit_log_pkey","definition":"CREATE UNIQUE INDEX score_audit_log_pkey ON public.score_audit_log USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"score_audit_log","permissive":"PERMISSIVE","policyname":"score_audit_insert_admin","schemaname":"public","with_check":"(is_system_admin(uid()) OR is_admin_or_higher(uid(), (tenant_org_id)::uuid) OR (actor_user_id = uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"score_audit_log","permissive":"PERMISSIVE","policyname":"score_audit_select_member","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"score_audit_log_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"score_dismissals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"score_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dismissed_until","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_score_dismissals_subject","definition":"CREATE INDEX idx_score_dismissals_subject ON public.score_dismissals USING btree (subject_type, subject_id)"},{"name":"idx_score_dismissals_user","definition":"CREATE INDEX idx_score_dismissals_user ON public.score_dismissals USING btree (user_id, score_type)"},{"name":"score_dismissals_pkey","definition":"CREATE UNIQUE INDEX score_dismissals_pkey ON public.score_dismissals USING btree (id)"},{"name":"score_dismissals_unique","definition":"CREATE UNIQUE INDEX score_dismissals_unique ON public.score_dismissals USING btree (user_id, score_type, subject_type, subject_id)"}],"policies":[{"cmd":"DELETE","qual":"((user_id = uid()) OR is_system_admin(uid()) OR is_admin_or_higher(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"score_dismissals","permissive":"PERMISSIVE","policyname":"score_dismissals_delete_own_or_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"score_dismissals","permissive":"PERMISSIVE","policyname":"score_dismissals_insert_self","schemaname":"public","with_check":"((user_id = uid()) AND is_tenant_member(tenant_org_id))"},{"cmd":"SELECT","qual":"((user_id = uid()) OR is_system_admin(uid()) OR is_admin_or_higher(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"score_dismissals","permissive":"PERMISSIVE","policyname":"score_dismissals_select_own_or_admin","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"score_dismissals_pkey","definition":"PRIMARY KEY (id)"},{"name":"score_dismissals_unique","definition":"UNIQUE (user_id, score_type, subject_type, subject_id)"}]},{"table":"score_models","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"score_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"weights","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"thresholds","type":"jsonb","default":"'{\"hot\": 90, \"worth\": 60, \"strong\": 75}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"min_visibility_score","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"weights_locked","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_score_models_lookup","definition":"CREATE INDEX idx_score_models_lookup ON public.score_models USING btree (score_type, tenant_org_id)"},{"name":"score_models_pkey","definition":"CREATE UNIQUE INDEX score_models_pkey ON public.score_models USING btree (id)"},{"name":"score_models_unique_per_tenant","definition":"CREATE UNIQUE INDEX score_models_unique_per_tenant ON public.score_models USING btree (tenant_org_id, score_type)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"score_models","permissive":"PERMISSIVE","policyname":"score_models_delete_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"score_models","permissive":"PERMISSIVE","policyname":"score_models_insert_admin","schemaname":"public","with_check":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)))"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(tenant_org_id) OR is_system_admin(uid()))","roles":["public"],"tablename":"score_models","permissive":"PERMISSIVE","policyname":"score_models_select_global_or_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR ((tenant_org_id IS NOT NULL) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)))","roles":["public"],"tablename":"score_models","permissive":"PERMISSIVE","policyname":"score_models_update_admin","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_score_models_updated_at","definition":"CREATE TRIGGER trg_score_models_updated_at BEFORE UPDATE ON score_models FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"score_models_pkey","definition":"PRIMARY KEY (id)"},{"name":"score_models_unique_per_tenant","definition":"UNIQUE (tenant_org_id, score_type)"}]},{"table":"security_alerts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"alert_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"severity","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"acknowledged_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolution_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_security_alerts_created","definition":"CREATE INDEX idx_security_alerts_created ON public.security_alerts USING btree (created_at DESC)"},{"name":"idx_security_alerts_severity","definition":"CREATE INDEX idx_security_alerts_severity ON public.security_alerts USING btree (severity)"},{"name":"idx_security_alerts_type","definition":"CREATE INDEX idx_security_alerts_type ON public.security_alerts USING btree (alert_type)"},{"name":"security_alerts_pkey","definition":"CREATE UNIQUE INDEX security_alerts_pkey ON public.security_alerts USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"security_alerts","permissive":"PERMISSIVE","policyname":"platform_admin_manage_security_alerts","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"security_alerts_pkey","definition":"PRIMARY KEY (id)"},{"name":"security_alerts_severity_check","definition":"CHECK (severity = ANY (ARRAY['low'::text, 'medium'::text, 'high'::text, 'critical'::text]))"}]},{"table":"security_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"success","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"failure_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"severity","type":"text","default":"'medium'::text","identity":"","not_null":false,"generated":""},{"name":"timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_security_events_email","definition":"CREATE INDEX idx_security_events_email ON public.security_events USING btree (email)"},{"name":"idx_security_events_severity","definition":"CREATE INDEX idx_security_events_severity ON public.security_events USING btree (severity)"},{"name":"idx_security_events_timestamp","definition":"CREATE INDEX idx_security_events_timestamp ON public.security_events USING btree (\"timestamp\" DESC)"},{"name":"idx_security_events_type","definition":"CREATE INDEX idx_security_events_type ON public.security_events USING btree (event_type)"},{"name":"idx_security_events_user_id","definition":"CREATE INDEX idx_security_events_user_id ON public.security_events USING btree (user_id)"},{"name":"security_events_pkey","definition":"CREATE UNIQUE INDEX security_events_pkey ON public.security_events USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"security_events","permissive":"PERMISSIVE","policyname":"platform_admin_view_security_events","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"security_events","permissive":"PERMISSIVE","policyname":"users_insert_own_security_events","schemaname":"public","with_check":"((user_id = uid()) OR is_system_admin(uid()))"}],"triggers":[],"constraints":[{"name":"security_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"security_events_severity_check","definition":"CHECK (severity = ANY (ARRAY['low'::text, 'medium'::text, 'high'::text, 'critical'::text]))"}]},{"table":"seminole_parcel_syncs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'running'::text","identity":"","not_null":true,"generated":""},{"name":"records_processed","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"records_added","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"records_updated","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"seminole_parcel_syncs_pkey","definition":"CREATE UNIQUE INDEX seminole_parcel_syncs_pkey ON public.seminole_parcel_syncs USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"seminole_parcel_syncs","permissive":"PERMISSIVE","policyname":"Admins can view sync history","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"seminole_parcel_syncs","permissive":"PERMISSIVE","policyname":"Service role can manage sync history","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"seminole_parcel_syncs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"seminole_parcels","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"parcel_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"owner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"site_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"site_city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"site_zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"square_feet","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"year_built","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"assessed_value","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"market_value","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"bedrooms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"bathrooms","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"lot_size_sqft","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"centroid_lat","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"centroid_lng","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_seminole_parcels_coords","definition":"CREATE INDEX idx_seminole_parcels_coords ON public.seminole_parcels USING btree (centroid_lat, centroid_lng) WHERE ((centroid_lat IS NOT NULL) AND (centroid_lng IS NOT NULL))"},{"name":"idx_seminole_parcels_parcel_id","definition":"CREATE INDEX idx_seminole_parcels_parcel_id ON public.seminole_parcels USING btree (parcel_id)"},{"name":"idx_seminole_parcels_site_address","definition":"CREATE INDEX idx_seminole_parcels_site_address ON public.seminole_parcels USING gin (to_tsvector('english'::regconfig, site_address))"},{"name":"idx_seminole_parcels_zip","definition":"CREATE INDEX idx_seminole_parcels_zip ON public.seminole_parcels USING btree (site_zip)"},{"name":"seminole_parcels_pkey","definition":"CREATE UNIQUE INDEX seminole_parcels_pkey ON public.seminole_parcels USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"seminole_parcels","permissive":"PERMISSIVE","policyname":"Service role can manage Seminole parcels","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"seminole_parcels","permissive":"PERMISSIVE","policyname":"seminole_parcels_select_admin_only","schemaname":"public","with_check":null}],"triggers":[{"name":"update_seminole_parcels_updated_at","definition":"CREATE TRIGGER update_seminole_parcels_updated_at BEFORE UPDATE ON seminole_parcels FOR EACH ROW EXECUTE FUNCTION update_seminole_parcels_updated_at()"}],"constraints":[{"name":"seminole_parcels_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"sequence_enrollment_progress","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"enrollment_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"step_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"result","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"sequence_enrollment_progress_pkey","definition":"CREATE UNIQUE INDEX sequence_enrollment_progress_pkey ON public.sequence_enrollment_progress USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"((EXISTS ( SELECT 1\n   FROM (sequence_enrollments se\n     JOIN communication_sequences cs ON ((cs.id = se.sequence_id)))\n  WHERE ((se.id = sequence_enrollment_progress.enrollment_id) AND is_tenant_member((cs.tenant_org_id)::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"sequence_enrollment_progress","permissive":"PERMISSIVE","policyname":"Tenant members can manage enrollment progress","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM (sequence_enrollments se\n     JOIN communication_sequences cs ON ((cs.id = se.sequence_id)))\n  WHERE ((se.id = sequence_enrollment_progress.enrollment_id) AND is_tenant_member((cs.tenant_org_id)::text)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM (sequence_enrollments se\n     JOIN communication_sequences cs ON ((cs.id = se.sequence_id)))\n  WHERE ((se.id = sequence_enrollment_progress.enrollment_id) AND is_tenant_member((cs.tenant_org_id)::text)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"sequence_enrollment_progress","permissive":"PERMISSIVE","policyname":"Tenant members can read enrollment progress","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"sequence_enrollment_progress_pkey","definition":"PRIMARY KEY (id)"},{"name":"sequence_enrollment_progress_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'in_progress'::text, 'completed'::text, 'skipped'::text, 'failed'::text]))"}]},{"table":"sequence_enrollments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"sequence_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"current_step","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"enrolled_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"enrolled_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"paused_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"unsubscribed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_action_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"step_history","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_sequence_enrollments_contact","definition":"CREATE INDEX idx_sequence_enrollments_contact ON public.sequence_enrollments USING btree (contact_id)"},{"name":"idx_sequence_enrollments_next_action","definition":"CREATE INDEX idx_sequence_enrollments_next_action ON public.sequence_enrollments USING btree (next_action_at) WHERE (status = 'active'::text)"},{"name":"sequence_enrollments_pkey","definition":"CREATE UNIQUE INDEX sequence_enrollments_pkey ON public.sequence_enrollments USING btree (id)"},{"name":"sequence_enrollments_sequence_id_contact_id_key","definition":"CREATE UNIQUE INDEX sequence_enrollments_sequence_id_contact_id_key ON public.sequence_enrollments USING btree (sequence_id, contact_id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"sequence_enrollments","permissive":"PERMISSIVE","policyname":"Tenant isolation for sequence_enrollments","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"sequence_enrollments_pkey","definition":"PRIMARY KEY (id)"},{"name":"sequence_enrollments_sequence_id_contact_id_key","definition":"UNIQUE (sequence_id, contact_id)"},{"name":"sequence_enrollments_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'paused'::text, 'completed'::text, 'unsubscribed'::text, 'bounced'::text, 'failed'::text]))"}]},{"table":"settlement_invoices","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"invoice_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"invoice_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"due_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_tone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"homeowner_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"insurance_carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"settlement_amount","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"deposit_amount","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"remaining_balance","type":"numeric","default":null,"identity":"","not_null":true,"generated":""},{"name":"payment_terms","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"invoice_html","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"original_total","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"insurance_payment","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"settlement_discount","type":"numeric","default":"0","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_settlement_invoices_contact","definition":"CREATE INDEX idx_settlement_invoices_contact ON public.settlement_invoices USING btree (contact_id)"},{"name":"idx_settlement_invoices_invoice_number","definition":"CREATE INDEX idx_settlement_invoices_invoice_number ON public.settlement_invoices USING btree (invoice_number)"},{"name":"idx_settlement_invoices_status","definition":"CREATE INDEX idx_settlement_invoices_status ON public.settlement_invoices USING btree (status)"},{"name":"idx_settlement_invoices_tenant","definition":"CREATE INDEX idx_settlement_invoices_tenant ON public.settlement_invoices USING btree (tenant_org_id)"},{"name":"settlement_invoices_pkey","definition":"CREATE UNIQUE INDEX settlement_invoices_pkey ON public.settlement_invoices USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"Users create tenant invoices","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) AND (created_by_user_id = uid()))"},{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"Users delete tenant invoices","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"Users update tenant invoices","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"Users view tenant invoices","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"si_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"si_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"si_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"si_update","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (settlement_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_delete_settlement_invoices","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_insert_settlement_invoices","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (settlement_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (settlement_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_update_settlement_invoices","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (settlement_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (settlement_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"settlement_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_view_settlement_invoices","schemaname":"public","with_check":null}],"triggers":[{"name":"settlement_invoices_updated_at","definition":"CREATE TRIGGER settlement_invoices_updated_at BEFORE UPDATE ON settlement_invoices FOR EACH ROW EXECUTE FUNCTION update_settlement_invoices_updated_at()"}],"constraints":[{"name":"settlement_invoices_pkey","definition":"PRIMARY KEY (id)"},{"name":"settlement_invoices_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'sent'::text, 'paid'::text, 'overdue'::text, 'cancelled'::text]))"},{"name":"settlement_invoices_template_tone_check","definition":"CHECK (template_tone = ANY (ARRAY['Friendly'::text, 'Standard'::text, 'Stern'::text]))"}]},{"table":"share_packets","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"referral_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"share_packets_pkey","definition":"CREATE UNIQUE INDEX share_packets_pkey ON public.share_packets USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"share_packets","permissive":"PERMISSIVE","policyname":"referral_creators_insert_packets","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM referrals r\n  WHERE ((r.id = share_packets.referral_id) AND is_tenant_member((r.from_tenant_id)::text))))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM referrals r\n  WHERE ((r.id = share_packets.referral_id) AND (is_tenant_member((r.from_tenant_id)::text) OR is_tenant_member((r.to_tenant_id)::text))))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"share_packets","permissive":"PERMISSIVE","policyname":"referral_participants_view_packets","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"share_packets_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"shared_claim_activity","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"shared_claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"activity_type","type":"text","default":"'stage_change'::text","identity":"","not_null":true,"generated":""},{"name":"field_changed","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"old_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"new_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_shared_claim_activity_claim","definition":"CREATE INDEX idx_shared_claim_activity_claim ON public.shared_claim_activity USING btree (shared_claim_id)"},{"name":"idx_shared_claim_activity_created","definition":"CREATE INDEX idx_shared_claim_activity_created ON public.shared_claim_activity USING btree (created_at DESC)"},{"name":"shared_claim_activity_pkey","definition":"CREATE UNIQUE INDEX shared_claim_activity_pkey ON public.shared_claim_activity USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_claim_participant(shared_claim_id, uid())","roles":["authenticated"],"tablename":"shared_claim_activity","permissive":"PERMISSIVE","policyname":"participants_view_activity","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"shared_claim_activity","permissive":"PERMISSIVE","policyname":"system_insert_activity","schemaname":"public","with_check":"is_claim_participant(shared_claim_id, uid())"}],"triggers":[],"constraints":[{"name":"shared_claim_activity_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"shared_claim_participants","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"shared_claim_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"shared_claim_role","default":"'other'::shared_claim_role","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"jobs_stage","type":"text","default":"'Not Started'::text","identity":"","not_null":false,"generated":""},{"name":"status","type":"shared_claim_status","default":"'invited'::shared_claim_status","identity":"","not_null":true,"generated":""},{"name":"invited_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"accepted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_shared_claim_participants_claim","definition":"CREATE INDEX idx_shared_claim_participants_claim ON public.shared_claim_participants USING btree (shared_claim_id)"},{"name":"idx_shared_claim_participants_contact","definition":"CREATE INDEX idx_shared_claim_participants_contact ON public.shared_claim_participants USING btree (contact_id)"},{"name":"idx_shared_claim_participants_status","definition":"CREATE INDEX idx_shared_claim_participants_status ON public.shared_claim_participants USING btree (status)"},{"name":"idx_shared_claim_participants_tenant","definition":"CREATE INDEX idx_shared_claim_participants_tenant ON public.shared_claim_participants USING btree (tenant_id)"},{"name":"shared_claim_participants_pkey","definition":"CREATE UNIQUE INDEX shared_claim_participants_pkey ON public.shared_claim_participants USING btree (id)"},{"name":"shared_claim_participants_shared_claim_id_tenant_id_key","definition":"CREATE UNIQUE INDEX shared_claim_participants_shared_claim_id_tenant_id_key ON public.shared_claim_participants USING btree (shared_claim_id, tenant_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"shared_claim_participants","permissive":"PERMISSIVE","policyname":"Claim creators can invite participants","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM shared_claims sc\n  WHERE ((sc.id = shared_claim_participants.shared_claim_id) AND (sc.created_by_user_id = uid())))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = shared_claim_participants.tenant_id) AND (utm.status = 'active'::text)))) OR (EXISTS ( SELECT 1\n   FROM shared_claims sc\n  WHERE ((sc.id = shared_claim_participants.shared_claim_id) AND (sc.created_by_user_id = uid())))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"shared_claim_participants","permissive":"PERMISSIVE","policyname":"Participants can update their own record","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_claim_participant_any_status(shared_claim_id, uid())","roles":["authenticated"],"tablename":"shared_claim_participants","permissive":"PERMISSIVE","policyname":"Users can view participants of their shared claims","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_log_shared_claim_stage_change","definition":"CREATE TRIGGER trg_log_shared_claim_stage_change AFTER UPDATE ON shared_claim_participants FOR EACH ROW EXECUTE FUNCTION log_shared_claim_stage_change()"},{"name":"update_shared_claim_participants_updated_at","definition":"CREATE TRIGGER update_shared_claim_participants_updated_at BEFORE UPDATE ON shared_claim_participants FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"shared_claim_participants_pkey","definition":"PRIMARY KEY (id)"},{"name":"shared_claim_participants_shared_claim_id_tenant_id_key","definition":"UNIQUE (shared_claim_id, tenant_id)"}]},{"table":"shared_claims","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"date_of_loss","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_stage","type":"text","default":"'New'::text","identity":"","not_null":true,"generated":""},{"name":"created_by_tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by_user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_shared_claims_created_by_tenant","definition":"CREATE INDEX idx_shared_claims_created_by_tenant ON public.shared_claims USING btree (created_by_tenant_id)"},{"name":"shared_claims_pkey","definition":"CREATE UNIQUE INDEX shared_claims_pkey ON public.shared_claims USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"shared_claims","permissive":"PERMISSIVE","policyname":"Authenticated users can create shared claims","schemaname":"public","with_check":"(created_by_user_id = uid())"},{"cmd":"UPDATE","qual":"is_claim_participant(id, uid())","roles":["authenticated"],"tablename":"shared_claims","permissive":"PERMISSIVE","policyname":"Participants can update shared claim stage","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_claim_participant_any_status(id, uid())","roles":["authenticated"],"tablename":"shared_claims","permissive":"PERMISSIVE","policyname":"Users can view shared claims they participate in","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_log_shared_claim_claim_stage_change","definition":"CREATE TRIGGER trg_log_shared_claim_claim_stage_change AFTER UPDATE ON shared_claims FOR EACH ROW EXECUTE FUNCTION log_shared_claim_claim_stage_change()"},{"name":"update_shared_claims_updated_at","definition":"CREATE TRIGGER update_shared_claims_updated_at BEFORE UPDATE ON shared_claims FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"shared_claims_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"short_stay_reservations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"unit_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"guest_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"guest_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"guest_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":"'manual'::text","identity":"","not_null":true,"generated":""},{"name":"external_booking_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"check_in","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"check_out","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'confirmed'::text","identity":"","not_null":true,"generated":""},{"name":"guest_count","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"total_amount","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"amount_paid","type":"numeric(12,2)","default":"0","identity":"","not_null":true,"generated":""},{"name":"payment_status","type":"text","default":"'unpaid'::text","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"short_stay_reservations_external_idx","definition":"CREATE UNIQUE INDEX short_stay_reservations_external_idx ON public.short_stay_reservations USING btree (tenant_id, source, external_booking_id) WHERE (external_booking_id IS NOT NULL)"},{"name":"short_stay_reservations_pkey","definition":"CREATE UNIQUE INDEX short_stay_reservations_pkey ON public.short_stay_reservations USING btree (id)"},{"name":"short_stay_reservations_tenant_dates_idx","definition":"CREATE INDEX short_stay_reservations_tenant_dates_idx ON public.short_stay_reservations USING btree (tenant_id, check_in, check_out)"},{"name":"vista_short_stay_no_overlap","definition":"CREATE INDEX vista_short_stay_no_overlap ON public.short_stay_reservations USING gist (tenant_id, unit_name, daterange(check_in, check_out, '[)'::text)) WHERE ((tenant_id = '71b397ba-b9ad-496b-914c-985d97dbb12e'::uuid) AND (status = ANY (ARRAY['confirmed'::text, 'checked_in'::text])))"}],"policies":[{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = short_stay_reservations.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))) OR (EXISTS ( SELECT 1\n   FROM user_roles r\n  WHERE ((r.user_id = uid()) AND (r.tenant_id = short_stay_reservations.tenant_id)))))","roles":["authenticated"],"tablename":"short_stay_reservations","permissive":"PERMISSIVE","policyname":"short_stay_reservations_member_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"short_stay_reservations","permissive":"PERMISSIVE","policyname":"short_stay_reservations_member_insert","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = short_stay_reservations.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))) OR (EXISTS ( SELECT 1\n   FROM user_roles r\n  WHERE ((r.user_id = uid()) AND (r.tenant_id = short_stay_reservations.tenant_id)))))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = short_stay_reservations.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))) OR (EXISTS ( SELECT 1\n   FROM user_roles r\n  WHERE ((r.user_id = uid()) AND (r.tenant_id = short_stay_reservations.tenant_id)))))","roles":["authenticated"],"tablename":"short_stay_reservations","permissive":"PERMISSIVE","policyname":"short_stay_reservations_member_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = short_stay_reservations.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))) OR (EXISTS ( SELECT 1\n   FROM user_roles r\n  WHERE ((r.user_id = uid()) AND (r.tenant_id = short_stay_reservations.tenant_id)))))","roles":["authenticated"],"tablename":"short_stay_reservations","permissive":"PERMISSIVE","policyname":"short_stay_reservations_member_update","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = short_stay_reservations.tenant_id) AND (COALESCE(m.status, 'active'::text) = 'active'::text)))) OR (EXISTS ( SELECT 1\n   FROM user_roles r\n  WHERE ((r.user_id = uid()) AND (r.tenant_id = short_stay_reservations.tenant_id)))))"}],"triggers":[],"constraints":[{"name":"short_stay_reservations_check","definition":"CHECK (check_out > check_in)"},{"name":"short_stay_reservations_created_by_fkey","definition":"FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL"},{"name":"short_stay_reservations_guest_count_check","definition":"CHECK (guest_count > 0)"},{"name":"short_stay_reservations_payment_status_check","definition":"CHECK (payment_status = ANY (ARRAY['unpaid'::text, 'partial'::text, 'paid'::text, 'refunded'::text]))"},{"name":"short_stay_reservations_pkey","definition":"PRIMARY KEY (id)"},{"name":"short_stay_reservations_status_check","definition":"CHECK (status = ANY (ARRAY['inquiry'::text, 'confirmed'::text, 'checked_in'::text, 'checked_out'::text, 'cancelled'::text]))"},{"name":"short_stay_reservations_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"vista_short_stay_no_overlap","definition":"EXCLUDE USING gist (tenant_id WITH =, unit_name WITH =, daterange(check_in, check_out, '[)'::text) WITH &&) WHERE (tenant_id = '71b397ba-b9ad-496b-914c-985d97dbb12e'::uuid AND (status = ANY (ARRAY['confirmed'::text, 'checked_in'::text])))"}]},{"table":"signed_agreements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"pending_signup_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"agreement_version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"agreement_html","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"signature","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"gear_election","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"workers_comp_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"esign_consent","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"signed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"signed_ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pdf_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pdf_drive_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreement_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"user_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_version_at_signing","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"assent_checkbox_accepted","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"electronic_records_consent","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"session_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"superseded_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"effective_date_at_signing","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"signer_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"declined_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"decline_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'signed'::text","identity":"","not_null":true,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_signed_agreements_pending_id","definition":"CREATE INDEX idx_signed_agreements_pending_id ON public.signed_agreements USING btree (pending_signup_id)"},{"name":"idx_signed_agreements_signed_at","definition":"CREATE INDEX idx_signed_agreements_signed_at ON public.signed_agreements USING btree (signed_at)"},{"name":"idx_signed_agreements_status","definition":"CREATE INDEX idx_signed_agreements_status ON public.signed_agreements USING btree (status) WHERE (status = 'signed'::text)"},{"name":"idx_signed_agreements_template_id","definition":"CREATE INDEX idx_signed_agreements_template_id ON public.signed_agreements USING btree (template_id)"},{"name":"idx_signed_agreements_type","definition":"CREATE INDEX idx_signed_agreements_type ON public.signed_agreements USING btree (agreement_type)"},{"name":"idx_signed_agreements_user_id","definition":"CREATE INDEX idx_signed_agreements_user_id ON public.signed_agreements USING btree (user_id)"},{"name":"idx_signed_agreements_user_tenant","definition":"CREATE INDEX idx_signed_agreements_user_tenant ON public.signed_agreements USING btree (user_id, tenant_id)"},{"name":"signed_agreements_event_booking_idx","definition":"CREATE INDEX signed_agreements_event_booking_idx ON public.signed_agreements USING btree (event_booking_id)"},{"name":"signed_agreements_pkey","definition":"CREATE UNIQUE INDEX signed_agreements_pkey ON public.signed_agreements USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(user_id = uid())","roles":["public"],"tablename":"signed_agreements","permissive":"PERMISSIVE","policyname":"Users can view own agreements","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"signed_agreements","permissive":"PERMISSIVE","policyname":"agreements_godmode_select","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((tenant_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_id))","roles":["public"],"tablename":"signed_agreements","permissive":"PERMISSIVE","policyname":"agreements_tenant_owner_select","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"signed_agreements","permissive":"PERMISSIVE","policyname":"agreements_user_insert_self","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["public"],"tablename":"signed_agreements","permissive":"PERMISSIVE","policyname":"agreements_user_select_own","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_signed_agreements_no_delete","definition":"CREATE TRIGGER trg_signed_agreements_no_delete BEFORE DELETE ON signed_agreements FOR EACH ROW EXECUTE FUNCTION block_mutation_append_only()"},{"name":"trg_signed_work_auth_to_job_request_ins","definition":"CREATE TRIGGER trg_signed_work_auth_to_job_request_ins AFTER INSERT ON signed_agreements FOR EACH ROW EXECUTE FUNCTION tg_create_job_request_from_signed_work_auth()"},{"name":"trg_signed_work_auth_to_job_request_upd","definition":"CREATE TRIGGER trg_signed_work_auth_to_job_request_upd AFTER UPDATE OF status ON signed_agreements FOR EACH ROW WHEN (new.status = 'signed'::text AND old.status IS DISTINCT FROM 'signed'::text) EXECUTE FUNCTION tg_create_job_request_from_signed_work_auth()"}],"constraints":[{"name":"chk_user_or_pending","definition":"CHECK (user_id IS NOT NULL AND pending_signup_id IS NULL OR user_id IS NULL AND pending_signup_id IS NOT NULL OR user_id IS NULL AND pending_signup_id IS NULL AND tenant_id IS NOT NULL AND signer_role IS NOT NULL)"},{"name":"signed_agreements_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"signed_agreements_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"site_config","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"config_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"config_value","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_config_key","definition":"CREATE INDEX idx_config_key ON public.site_config USING btree (config_key)"},{"name":"site_config_config_key_tenant_org_id_key","definition":"CREATE UNIQUE INDEX site_config_config_key_tenant_org_id_key ON public.site_config USING btree (config_key, tenant_org_id)"},{"name":"site_config_key_tenant_unique","definition":"CREATE UNIQUE INDEX site_config_key_tenant_unique ON public.site_config USING btree (config_key, tenant_org_id)"},{"name":"site_config_pkey","definition":"CREATE UNIQUE INDEX site_config_pkey ON public.site_config USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((uid() IS NOT NULL) AND ((tenant_org_id IS NULL) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.tenant_id = (site_config.tenant_org_id)::uuid))))))","roles":["public"],"tablename":"site_config","permissive":"PERMISSIVE","policyname":"Authenticated users view configs","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"site_config","permissive":"PERMISSIVE","policyname":"platform_admin_manage_site_config","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid) AND (category = 'workflow_overrides'::text) AND (config_key ~~ 'workflow_overrides_%'::text))","roles":["authenticated"],"tablename":"site_config","permissive":"PERMISSIVE","policyname":"tenant_owner_admin_manage_workflow_overrides_site_config","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid) AND (category = 'workflow_overrides'::text) AND (config_key ~~ 'workflow_overrides_%'::text))"}],"triggers":[{"name":"update_site_config_updated_at","definition":"CREATE TRIGGER update_site_config_updated_at BEFORE UPDATE ON site_config FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"site_config_config_key_tenant_org_id_key","definition":"UNIQUE (config_key, tenant_org_id)"},{"name":"site_config_key_tenant_unique","definition":"UNIQUE (config_key, tenant_org_id)"},{"name":"site_config_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"sms_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"direction","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'sent'::text","identity":"","not_null":false,"generated":""},{"name":"twilio_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_sms_history_contact","definition":"CREATE INDEX idx_sms_history_contact ON public.sms_history USING btree (contact_id)"},{"name":"idx_sms_history_created","definition":"CREATE INDEX idx_sms_history_created ON public.sms_history USING btree (created_at DESC)"},{"name":"idx_sms_history_tenant","definition":"CREATE INDEX idx_sms_history_tenant ON public.sms_history USING btree (tenant_id)"},{"name":"sms_history_pkey","definition":"CREATE UNIQUE INDEX sms_history_pkey ON public.sms_history USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"sms_history","permissive":"PERMISSIVE","policyname":"Users can create SMS history for their tenant","schemaname":"public","with_check":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"sms_history","permissive":"PERMISSIVE","policyname":"Users can view SMS history for their tenant","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_owner_capture_unknown_inbound_sms_contact","definition":"CREATE TRIGGER trg_owner_capture_unknown_inbound_sms_contact BEFORE INSERT ON sms_history FOR EACH ROW EXECUTE FUNCTION owner_capture_unknown_inbound_sms_contact()"},{"name":"trg_owner_sms_history_dedupe_sid_guard","definition":"CREATE TRIGGER trg_owner_sms_history_dedupe_sid_guard BEFORE INSERT ON sms_history FOR EACH ROW EXECUTE FUNCTION owner_sms_history_dedupe_sid_guard()"}],"constraints":[{"name":"sms_history_direction_check","definition":"CHECK (direction = ANY (ARRAY['inbound'::text, 'outbound'::text]))"},{"name":"sms_history_pkey","definition":"PRIMARY KEY (id)"},{"name":"sms_history_status_check","definition":"CHECK (status = ANY (ARRAY['queued'::text, 'sent'::text, 'delivered'::text, 'failed'::text, 'received'::text]))"}]},{"table":"sms_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'general'::text","identity":"","not_null":false,"generated":""},{"name":"variables","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_sms_templates_active","definition":"CREATE INDEX idx_sms_templates_active ON public.sms_templates USING btree (tenant_id, is_active)"},{"name":"idx_sms_templates_tenant","definition":"CREATE INDEX idx_sms_templates_tenant ON public.sms_templates USING btree (tenant_id)"},{"name":"sms_templates_pkey","definition":"CREATE UNIQUE INDEX sms_templates_pkey ON public.sms_templates USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"sms_templates","permissive":"PERMISSIVE","policyname":"Users can create SMS templates for their tenant","schemaname":"public","with_check":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))"},{"cmd":"DELETE","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"sms_templates","permissive":"PERMISSIVE","policyname":"Users can delete SMS templates for their tenant","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"sms_templates","permissive":"PERMISSIVE","policyname":"Users can update SMS templates for their tenant","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"sms_templates","permissive":"PERMISSIVE","policyname":"Users can view SMS templates for their tenant","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"sms_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"sql_execution_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"executed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"executed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"query_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"execution_status","type":"text","default":"'success'::text","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rows_affected","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"execution_time_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"sql_execution_history_pkey","definition":"CREATE UNIQUE INDEX sql_execution_history_pkey ON public.sql_execution_history USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"sql_execution_history","permissive":"PERMISSIVE","policyname":"platform_admin_manage_sql_history","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"sql_execution_history_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"storm_attribution_links","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"storm_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_zone_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"entity_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"entity_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"attribution_method","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"confidence_score","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"evidence_json","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by_module","type":"text","default":"'storm-attribution'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"storm_attribution_links_entity_idx","definition":"CREATE INDEX storm_attribution_links_entity_idx ON public.storm_attribution_links USING btree (tenant_id, entity_type, entity_id)"},{"name":"storm_attribution_links_pkey","definition":"CREATE UNIQUE INDEX storm_attribution_links_pkey ON public.storm_attribution_links USING btree (id)"},{"name":"storm_attribution_links_storm_idx","definition":"CREATE INDEX storm_attribution_links_storm_idx ON public.storm_attribution_links USING btree (tenant_id, storm_id, created_at DESC) WHERE (storm_id IS NOT NULL)"},{"name":"storm_attribution_links_zone_idx","definition":"CREATE INDEX storm_attribution_links_zone_idx ON public.storm_attribution_links USING btree (tenant_id, storm_zone_id, created_at DESC) WHERE (storm_zone_id IS NOT NULL)"}],"policies":[{"cmd":"SELECT","qual":"ai_user_in_tenant(tenant_id)","roles":["authenticated"],"tablename":"storm_attribution_links","permissive":"PERMISSIVE","policyname":"storm_attribution_links_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"storm_attribution_links_attribution_method_check","definition":"CHECK (attribution_method = ANY (ARRAY['address_match'::text, 'zip_match'::text, 'geo_match'::text, 'campaign_match'::text, 'manual'::text, 'rep_assignment'::text, 'call_source'::text, 'lead_source'::text, 'appointment_location'::text, 'job_location'::text]))"},{"name":"storm_attribution_links_confidence_score_check","definition":"CHECK (confidence_score IS NULL OR confidence_score >= 0::numeric AND confidence_score <= 1::numeric)"},{"name":"storm_attribution_links_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"storm_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"county","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"state","type":"text","default":"'FL'::text","identity":"","not_null":true,"generated":""},{"name":"zip_prefix","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_date","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"wind_mph","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"hail_inches","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"qualifies","type":"boolean","default":"((wind_mph >= (60)::numeric) OR (hail_inches >= 0.75))","identity":"","not_null":false,"generated":"s"},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"lat","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"lng","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"location_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_direction_deg","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"storm_speed_mph","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_minutes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"affected_polygon","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"path_width_miles","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"geometry_source","type":"text","default":"'none'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_storm_events_coordinates","definition":"CREATE INDEX idx_storm_events_coordinates ON public.storm_events USING btree (lat, lng) WHERE ((lat IS NOT NULL) AND (lng IS NOT NULL))"},{"name":"idx_storm_events_county","definition":"CREATE INDEX idx_storm_events_county ON public.storm_events USING btree (county, state)"},{"name":"idx_storm_events_county_date","definition":"CREATE INDEX idx_storm_events_county_date ON public.storm_events USING btree (county, event_date DESC)"},{"name":"idx_storm_events_date","definition":"CREATE INDEX idx_storm_events_date ON public.storm_events USING btree (event_date DESC)"},{"name":"idx_storm_events_qualifies","definition":"CREATE INDEX idx_storm_events_qualifies ON public.storm_events USING btree (qualifies) WHERE (qualifies = true)"},{"name":"idx_storm_events_unique","definition":"CREATE UNIQUE INDEX idx_storm_events_unique ON public.storm_events USING btree (county, event_date, COALESCE(wind_mph, (0)::numeric), COALESCE(hail_inches, (0)::numeric))"},{"name":"idx_storm_events_zip_prefix","definition":"CREATE INDEX idx_storm_events_zip_prefix ON public.storm_events USING btree (zip_prefix)"},{"name":"storm_events_pkey","definition":"CREATE UNIQUE INDEX storm_events_pkey ON public.storm_events USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"storm_events","permissive":"PERMISSIVE","policyname":"Admins can manage storm events","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"true","roles":["public"],"tablename":"storm_events","permissive":"PERMISSIVE","policyname":"Storm events are publicly readable","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_mark_scores_stale_on_storm","definition":"CREATE TRIGGER trg_mark_scores_stale_on_storm AFTER INSERT ON storm_events FOR EACH ROW EXECUTE FUNCTION mark_scores_stale_on_storm()"},{"name":"trg_storm_events_mark_scores_stale","definition":"CREATE TRIGGER trg_storm_events_mark_scores_stale AFTER INSERT ON storm_events FOR EACH ROW EXECUTE FUNCTION mark_scores_stale_on_storm_event()"},{"name":"update_storm_events_updated_at","definition":"CREATE TRIGGER update_storm_events_updated_at BEFORE UPDATE ON storm_events FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"storm_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"storm_report_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"report_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"actor_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"details","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_storm_report_audit_report","definition":"CREATE INDEX idx_storm_report_audit_report ON public.storm_report_audit USING btree (report_id, created_at DESC)"},{"name":"storm_report_audit_pkey","definition":"CREATE UNIQUE INDEX storm_report_audit_pkey ON public.storm_report_audit USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"storm_report_audit","permissive":"PERMISSIVE","policyname":"Tenant members can insert audit","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) AND (actor_id = uid()))"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"storm_report_audit","permissive":"PERMISSIVE","policyname":"Tenant members can view audit","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"storm_report_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"storm_report_deliveries","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"report_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"recipient","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'queued'::text","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_storm_report_deliveries_report","definition":"CREATE INDEX idx_storm_report_deliveries_report ON public.storm_report_deliveries USING btree (report_id)"},{"name":"idx_storm_report_deliveries_tenant","definition":"CREATE INDEX idx_storm_report_deliveries_tenant ON public.storm_report_deliveries USING btree (tenant_org_id)"},{"name":"storm_report_deliveries_pkey","definition":"CREATE UNIQUE INDEX storm_report_deliveries_pkey ON public.storm_report_deliveries USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (storm_report_deliveries.tenant_org_id)::uuid) AND (user_roles.role = ANY (ARRAY['Admin'::app_role, 'GodMode'::app_role, 'Owner'::app_role]))))) OR is_system_admin(uid()))","roles":["public"],"tablename":"storm_report_deliveries","permissive":"PERMISSIVE","policyname":"Admins delete storm report deliveries","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"storm_report_deliveries","permissive":"PERMISSIVE","policyname":"Tenant members insert storm report deliveries","schemaname":"public","with_check":"(((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))","roles":["public"],"tablename":"storm_report_deliveries","permissive":"PERMISSIVE","policyname":"Tenant members view storm report deliveries","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"storm_report_deliveries_channel_check","definition":"CHECK (channel = ANY (ARRAY['email'::text, 'sms'::text]))"},{"name":"storm_report_deliveries_pkey","definition":"PRIMARY KEY (id)"},{"name":"storm_report_deliveries_status_check","definition":"CHECK (status = ANY (ARRAY['queued'::text, 'sent'::text, 'failed'::text]))"}]},{"table":"storm_report_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"report_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"share_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"device_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"browser","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_storm_report_events_report","definition":"CREATE INDEX idx_storm_report_events_report ON public.storm_report_events USING btree (report_id, event_timestamp DESC)"},{"name":"idx_storm_report_events_tenant","definition":"CREATE INDEX idx_storm_report_events_tenant ON public.storm_report_events USING btree (tenant_org_id, event_timestamp DESC)"},{"name":"idx_storm_report_events_type","definition":"CREATE INDEX idx_storm_report_events_type ON public.storm_report_events USING btree (report_id, event_type)"},{"name":"storm_report_events_pkey","definition":"CREATE UNIQUE INDEX storm_report_events_pkey ON public.storm_report_events USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"storm_report_events","permissive":"PERMISSIVE","policyname":"tenant_members_read_storm_report_events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"storm_report_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"storm_report_questions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"report_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"share_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"question","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"resolved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_storm_report_questions_report","definition":"CREATE INDEX idx_storm_report_questions_report ON public.storm_report_questions USING btree (report_id, created_at DESC)"},{"name":"storm_report_questions_pkey","definition":"CREATE UNIQUE INDEX storm_report_questions_pkey ON public.storm_report_questions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"storm_report_questions","permissive":"PERMISSIVE","policyname":"tenant_members_read_storm_report_questions","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"storm_report_questions","permissive":"PERMISSIVE","policyname":"tenant_members_update_storm_report_questions","schemaname":"public","with_check":"is_tenant_member(tenant_org_id)"}],"triggers":[],"constraints":[{"name":"storm_report_questions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"storm_reports","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"storage_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"file_size_bytes","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"photo_ids","type":"uuid[]","default":"'{}'::uuid[]","identity":"","not_null":false,"generated":""},{"name":"storm_event_ids","type":"uuid[]","default":"'{}'::uuid[]","identity":"","not_null":false,"generated":""},{"name":"ai_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_concern_level","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"generated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"generated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"shared_with_homeowner_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"share_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"view_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"last_viewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"primary_storm_event_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tone","type":"text","default":"'strict'::text","identity":"","not_null":true,"generated":""},{"name":"ai_summary_override","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"photo_caption_overrides","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"hidden_photo_ids","type":"uuid[]","default":"'{}'::uuid[]","identity":"","not_null":true,"generated":""},{"name":"hidden_storm_event_ids","type":"uuid[]","default":"'{}'::uuid[]","identity":"","not_null":true,"generated":""},{"name":"concern_level_override","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"revoked_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"share_requires_approval","type":"boolean","default":"true","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_storm_reports_contact","definition":"CREATE INDEX idx_storm_reports_contact ON public.storm_reports USING btree (contact_id)"},{"name":"idx_storm_reports_generated_at","definition":"CREATE INDEX idx_storm_reports_generated_at ON public.storm_reports USING btree (generated_at DESC)"},{"name":"idx_storm_reports_tenant","definition":"CREATE INDEX idx_storm_reports_tenant ON public.storm_reports USING btree (tenant_org_id)"},{"name":"storm_reports_pkey","definition":"CREATE UNIQUE INDEX storm_reports_pkey ON public.storm_reports USING btree (id)"},{"name":"storm_reports_share_token_key","definition":"CREATE UNIQUE INDEX storm_reports_share_token_key ON public.storm_reports USING btree (share_token)"}],"policies":[{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND (user_roles.tenant_id = (storm_reports.tenant_org_id)::uuid) AND (user_roles.role = ANY (ARRAY['Admin'::app_role, 'GodMode'::app_role, 'Owner'::app_role]))))) OR is_system_admin(uid()))","roles":["public"],"tablename":"storm_reports","permissive":"PERMISSIVE","policyname":"Admins can delete storm reports","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"storm_reports","permissive":"PERMISSIVE","policyname":"Tenant members can create storm reports","schemaname":"public","with_check":"(((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"(((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))","roles":["public"],"tablename":"storm_reports","permissive":"PERMISSIVE","policyname":"Tenant members can update storm reports","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(((tenant_org_id)::uuid IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) OR is_system_admin(uid()))","roles":["public"],"tablename":"storm_reports","permissive":"PERMISSIVE","policyname":"Tenant members can view storm reports","schemaname":"public","with_check":null}],"triggers":[{"name":"update_storm_reports_updated_at","definition":"CREATE TRIGGER update_storm_reports_updated_at BEFORE UPDATE ON storm_reports FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"storm_reports_ai_concern_level_check","definition":"CHECK (ai_concern_level = ANY (ARRAY['low'::text, 'medium'::text, 'high'::text]))"},{"name":"storm_reports_concern_level_override_check","definition":"CHECK (concern_level_override IS NULL OR (concern_level_override = ANY (ARRAY['low'::text, 'medium'::text, 'high'::text, 'all_clear'::text])))"},{"name":"storm_reports_pkey","definition":"PRIMARY KEY (id)"},{"name":"storm_reports_share_token_key","definition":"UNIQUE (share_token)"},{"name":"storm_reports_tone_check","definition":"CHECK (tone = ANY (ARRAY['strict'::text, 'type_hinted'::text]))"}]},{"table":"stripe_webhook_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"stripe_event_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"environment","type":"text","default":"'sandbox'::text","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"processed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"stripe_webhook_events_pkey","definition":"CREATE UNIQUE INDEX stripe_webhook_events_pkey ON public.stripe_webhook_events USING btree (id)"},{"name":"stripe_webhook_events_stripe_event_id_key","definition":"CREATE UNIQUE INDEX stripe_webhook_events_stripe_event_id_key ON public.stripe_webhook_events USING btree (stripe_event_id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"stripe_webhook_events","permissive":"PERMISSIVE","policyname":"Only system admins can read webhook events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"stripe_webhook_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"stripe_webhook_events_stripe_event_id_key","definition":"UNIQUE (stripe_event_id)"}]},{"table":"subscription_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_plan_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_plan_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"actor_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_subscription_events_tenant","definition":"CREATE INDEX idx_subscription_events_tenant ON public.subscription_events USING btree (tenant_id, created_at DESC)"},{"name":"subscription_events_pkey","definition":"CREATE UNIQUE INDEX subscription_events_pkey ON public.subscription_events USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"subscription_events","permissive":"PERMISSIVE","policyname":"Only system admins write subscription events","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = subscription_events.tenant_id) AND (m.status = 'active'::text)))))","roles":["public"],"tablename":"subscription_events","permissive":"PERMISSIVE","policyname":"Tenant members read subscription events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"subscription_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"suppressed_emails","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_suppressed_emails_email","definition":"CREATE INDEX idx_suppressed_emails_email ON public.suppressed_emails USING btree (email)"},{"name":"suppressed_emails_email_key","definition":"CREATE UNIQUE INDEX suppressed_emails_email_key ON public.suppressed_emails USING btree (email)"},{"name":"suppressed_emails_pkey","definition":"CREATE UNIQUE INDEX suppressed_emails_pkey ON public.suppressed_emails USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"suppressed_emails","permissive":"PERMISSIVE","policyname":"Service role can insert suppressed emails","schemaname":"public","with_check":"(role() = 'service_role'::text)"},{"cmd":"SELECT","qual":"(role() = 'service_role'::text)","roles":["public"],"tablename":"suppressed_emails","permissive":"PERMISSIVE","policyname":"Service role can read suppressed emails","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"suppressed_emails_email_key","definition":"UNIQUE (email)"},{"name":"suppressed_emails_pkey","definition":"PRIMARY KEY (id)"},{"name":"suppressed_emails_reason_check","definition":"CHECK (reason = ANY (ARRAY['unsubscribe'::text, 'bounce'::text, 'complaint'::text]))"}]},{"table":"system_health_metrics","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"metric_category","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metric_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"value","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'healthy'::text","identity":"","not_null":false,"generated":""},{"name":"details","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"timestamp","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_system_health_category","definition":"CREATE INDEX idx_system_health_category ON public.system_health_metrics USING btree (metric_category)"},{"name":"idx_system_health_timestamp","definition":"CREATE INDEX idx_system_health_timestamp ON public.system_health_metrics USING btree (\"timestamp\" DESC)"},{"name":"system_health_metrics_pkey","definition":"CREATE UNIQUE INDEX system_health_metrics_pkey ON public.system_health_metrics USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"system_health_metrics","permissive":"PERMISSIVE","policyname":"admins_insert_health_metrics","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"system_health_metrics","permissive":"PERMISSIVE","policyname":"platform_admin_view_system_health","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"system_health_metrics_pkey","definition":"PRIMARY KEY (id)"},{"name":"system_health_metrics_status_check","definition":"CHECK (status = ANY (ARRAY['healthy'::text, 'degraded'::text, 'critical'::text]))"}]},{"table":"system_variable_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenancy_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variable_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variable_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variable_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"variable_type","type":"variable_type","default":"'text'::variable_type","identity":"","not_null":true,"generated":""},{"name":"scope","type":"variable_scope","default":"'workflow'::variable_scope","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_system_variable_templates_category","definition":"CREATE INDEX idx_system_variable_templates_category ON public.system_variable_templates USING btree (category)"},{"name":"idx_system_variable_templates_scope","definition":"CREATE INDEX idx_system_variable_templates_scope ON public.system_variable_templates USING btree (scope)"},{"name":"idx_system_variable_templates_tenancy","definition":"CREATE INDEX idx_system_variable_templates_tenancy ON public.system_variable_templates USING btree (tenancy_type)"},{"name":"system_variable_templates_pkey","definition":"CREATE UNIQUE INDEX system_variable_templates_pkey ON public.system_variable_templates USING btree (id)"},{"name":"system_variable_templates_tenancy_type_variable_key_key","definition":"CREATE UNIQUE INDEX system_variable_templates_tenancy_type_variable_key_key ON public.system_variable_templates USING btree (tenancy_type, variable_key)"}],"policies":[{"cmd":"SELECT","qual":"(is_active = true)","roles":["authenticated"],"tablename":"system_variable_templates","permissive":"PERMISSIVE","policyname":"Authenticated users can view system variable templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"system_variable_templates","permissive":"PERMISSIVE","policyname":"platform_admin_manage_system_variable_templates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"update_system_variable_templates_updated_at","definition":"CREATE TRIGGER update_system_variable_templates_updated_at BEFORE UPDATE ON system_variable_templates FOR EACH ROW EXECUTE FUNCTION update_system_variable_templates_updated_at()"}],"constraints":[{"name":"system_variable_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"system_variable_templates_tenancy_type_variable_key_key","definition":"UNIQUE (tenancy_type, variable_key)"}]},{"table":"tarping_invoices","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"invoice_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"invoice_date","type":"date","default":"CURRENT_DATE","identity":"","not_null":true,"generated":""},{"name":"terms","type":"text","default":"'Upon Receipt'::text","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'draft'::text","identity":"","not_null":false,"generated":""},{"name":"insured_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"insured_poa","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"insurance_carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"materials_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"labor_items","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"materials_subtotal","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"labor_subtotal","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"grand_total","type":"numeric","default":"0","identity":"","not_null":false,"generated":""},{"name":"service_description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"important_notice","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"photo_urls","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"pdf_file_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pdf_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"paid_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"crew_size","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"anchor_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"distance_note","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"special_conditions","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"trip_miles","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"trip_hours","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"date_of_loss","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tarping_invoices_contact","definition":"CREATE INDEX idx_tarping_invoices_contact ON public.tarping_invoices USING btree (contact_id)"},{"name":"idx_tarping_invoices_invoice_number","definition":"CREATE INDEX idx_tarping_invoices_invoice_number ON public.tarping_invoices USING btree (invoice_number)"},{"name":"idx_tarping_invoices_status","definition":"CREATE INDEX idx_tarping_invoices_status ON public.tarping_invoices USING btree (status)"},{"name":"idx_tarping_invoices_tenant","definition":"CREATE INDEX idx_tarping_invoices_tenant ON public.tarping_invoices USING btree (tenant_org_id)"},{"name":"tarping_invoices_pkey","definition":"CREATE UNIQUE INDEX tarping_invoices_pkey ON public.tarping_invoices USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"Users create tenant tarping invoices","schemaname":"public","with_check":"((tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid()))) AND (created_by = uid()))"},{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"Users delete tenant tarping invoices","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"Users update tenant tarping invoices","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"Users view tenant tarping invoices","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (tarping_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_delete_tarping_invoices","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_insert_tarping_invoices","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (tarping_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"UPDATE","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (tarping_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_update_tarping_invoices","schemaname":"public","with_check":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (tarping_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = (tarping_invoices.tenant_org_id)::uuid)))) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"tenant_users_view_tarping_invoices","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"ti_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"ti_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"ti_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"tarping_invoices","permissive":"PERMISSIVE","policyname":"ti_update","schemaname":"public","with_check":null}],"triggers":[{"name":"tarping_invoices_updated_at","definition":"CREATE TRIGGER tarping_invoices_updated_at BEFORE UPDATE ON tarping_invoices FOR EACH ROW EXECUTE FUNCTION update_tarping_invoices_updated_at()"}],"constraints":[{"name":"tarping_invoices_pkey","definition":"PRIMARY KEY (id)"},{"name":"tarping_invoices_status_check","definition":"CHECK (status = ANY (ARRAY['draft'::text, 'sent'::text, 'paid'::text, 'cancelled'::text]))"}]},{"table":"tasks","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_to","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority","type":"text","default":"'medium'::text","identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"due_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reminder_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"claim_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_kind","type":"text","default":"(metadata ->> 'source_kind'::text)","identity":"","not_null":false,"generated":"s"},{"name":"source_id","type":"text","default":"(metadata ->> 'source_id'::text)","identity":"","not_null":false,"generated":"s"},{"name":"canonical_contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tasks_assigned_to","definition":"CREATE INDEX idx_tasks_assigned_to ON public.tasks USING btree (assigned_to)"},{"name":"idx_tasks_contact_id","definition":"CREATE INDEX idx_tasks_contact_id ON public.tasks USING btree (contact_id)"},{"name":"idx_tasks_due_date","definition":"CREATE INDEX idx_tasks_due_date ON public.tasks USING btree (due_date)"},{"name":"idx_tasks_status","definition":"CREATE INDEX idx_tasks_status ON public.tasks USING btree (status)"},{"name":"idx_tasks_tenant_claim","definition":"CREATE INDEX idx_tasks_tenant_claim ON public.tasks USING btree (tenant_id, claim_id) WHERE (claim_id IS NOT NULL)"},{"name":"idx_tasks_tenant_id","definition":"CREATE INDEX idx_tasks_tenant_id ON public.tasks USING btree (tenant_id)"},{"name":"tasks_pkey","definition":"CREATE UNIQUE INDEX tasks_pkey ON public.tasks USING btree (id)"},{"name":"tasks_tenant_source_columns_uidx","definition":"CREATE UNIQUE INDEX tasks_tenant_source_columns_uidx ON public.tasks USING btree (tenant_id, source_kind, source_id) WHERE ((source_kind IS NOT NULL) AND (source_id IS NOT NULL))"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"tasks","permissive":"PERMISSIVE","policyname":"Users create tenant tasks","schemaname":"public","with_check":"((uid() = user_id) AND (is_tenant_member(tenant_id) OR is_system_admin()))"},{"cmd":"DELETE","qual":"(((uid() = user_id) OR (uid() = assigned_to)) AND (is_tenant_member(tenant_id) OR is_system_admin()))","roles":["public"],"tablename":"tasks","permissive":"PERMISSIVE","policyname":"Users delete their tasks","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((uid() = assigned_to) OR (uid() = user_id))","roles":["public"],"tablename":"tasks","permissive":"PERMISSIVE","policyname":"Users update their tasks","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((uid() = assigned_to) OR (uid() = user_id) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = tasks.tenant_id)))))","roles":["public"],"tablename":"tasks","permissive":"PERMISSIVE","policyname":"Users view assigned tasks","schemaname":"public","with_check":null}],"triggers":[{"name":"tasks_updated_at","definition":"CREATE TRIGGER tasks_updated_at BEFORE UPDATE ON tasks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"},{"name":"trg_enforce_task_claim_context","definition":"CREATE TRIGGER trg_enforce_task_claim_context BEFORE INSERT OR UPDATE OF claim_id, contact_id, tenant_id ON tasks FOR EACH ROW EXECUTE FUNCTION enforce_task_claim_context()"}],"constraints":[{"name":"tasks_canonical_contact_fkey","definition":"FOREIGN KEY (canonical_contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"tasks_claim_id_fkey","definition":"FOREIGN KEY (claim_id) REFERENCES contact_claims(id) ON DELETE SET NULL"},{"name":"tasks_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"template_studio_publish_receipts","schema":"public","columns":[{"name":"id","type":"bigint","default":null,"identity":"d","not_null":true,"generated":""},{"name":"template_version_id","type":"bigint","default":null,"identity":"","not_null":true,"generated":""},{"name":"receipt_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"receipt","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":"uid()","identity":"","not_null":false,"generated":""},{"name":"created_by_label","type":"text","default":"'GodMode'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_template_studio_receipts_version","definition":"CREATE INDEX idx_template_studio_receipts_version ON public.template_studio_publish_receipts USING btree (template_version_id, created_at DESC)"},{"name":"template_studio_publish_receipts_pkey","definition":"CREATE UNIQUE INDEX template_studio_publish_receipts_pkey ON public.template_studio_publish_receipts USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"can_manage_experience_studio()","roles":["authenticated"],"tablename":"template_studio_publish_receipts","permissive":"PERMISSIVE","policyname":"experience studio admins manage receipts","schemaname":"public","with_check":"can_manage_experience_studio()"},{"cmd":"ALL","qual":"is_manager_pm_or_higher(uid(), NULL::uuid)","roles":["authenticated"],"tablename":"template_studio_publish_receipts","permissive":"PERMISSIVE","policyname":"template studio godmode all receipts","schemaname":"public","with_check":"is_manager_pm_or_higher(uid(), NULL::uuid)"},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"template_studio_publish_receipts","permissive":"PERMISSIVE","policyname":"template studio platform admin insert receipts","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"},{"cmd":"SELECT","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_publish_receipts","permissive":"PERMISSIVE","policyname":"template studio platform admin read receipts","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"template_studio_publish_receipts_pkey","definition":"PRIMARY KEY (id)"},{"name":"template_studio_publish_receipts_receipt_status_check","definition":"CHECK (receipt_status = ANY (ARRAY['LOCAL_DRAFT'::text, 'VALIDATED_DRAFT'::text, 'BLOCKED_DRAFT'::text, 'PUBLISHED'::text, 'RETIRED'::text]))"},{"name":"template_studio_publish_receipts_template_version_id_fkey","definition":"FOREIGN KEY (template_version_id) REFERENCES template_studio_template_versions(id) ON DELETE CASCADE"}]},{"table":"template_studio_template_versions","schema":"public","columns":[{"name":"id","type":"bigint","default":null,"identity":"d","not_null":true,"generated":""},{"name":"template_id","type":"bigint","default":null,"identity":"","not_null":true,"generated":""},{"name":"version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"version_status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"schema_version","type":"text","default":"'template-studio.v1'::text","identity":"","not_null":true,"generated":""},{"name":"payload","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"validation_receipt","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":"uid()","identity":"","not_null":false,"generated":""},{"name":"created_by_label","type":"text","default":"'GodMode'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"published_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"published_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_template_studio_versions_template","definition":"CREATE INDEX idx_template_studio_versions_template ON public.template_studio_template_versions USING btree (template_id, version_status, created_at DESC)"},{"name":"template_studio_template_versions_pkey","definition":"CREATE UNIQUE INDEX template_studio_template_versions_pkey ON public.template_studio_template_versions USING btree (id)"},{"name":"template_studio_template_versions_template_id_version_key","definition":"CREATE UNIQUE INDEX template_studio_template_versions_template_id_version_key ON public.template_studio_template_versions USING btree (template_id, version)"}],"policies":[{"cmd":"ALL","qual":"can_manage_experience_studio()","roles":["authenticated"],"tablename":"template_studio_template_versions","permissive":"PERMISSIVE","policyname":"experience studio admins manage versions","schemaname":"public","with_check":"can_manage_experience_studio()"},{"cmd":"ALL","qual":"is_manager_pm_or_higher(uid(), NULL::uuid)","roles":["authenticated"],"tablename":"template_studio_template_versions","permissive":"PERMISSIVE","policyname":"template studio godmode all versions","schemaname":"public","with_check":"is_manager_pm_or_higher(uid(), NULL::uuid)"},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"template_studio_template_versions","permissive":"PERMISSIVE","policyname":"template studio platform admin insert versions","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"},{"cmd":"SELECT","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_template_versions","permissive":"PERMISSIVE","policyname":"template studio platform admin read versions","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_template_versions","permissive":"PERMISSIVE","policyname":"template studio platform admin update versions","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"}],"triggers":[],"constraints":[{"name":"template_studio_template_versions_pkey","definition":"PRIMARY KEY (id)"},{"name":"template_studio_template_versions_template_id_fkey","definition":"FOREIGN KEY (template_id) REFERENCES template_studio_templates(id) ON DELETE CASCADE"},{"name":"template_studio_template_versions_template_id_version_key","definition":"UNIQUE (template_id, version)"},{"name":"template_studio_template_versions_version_status_check","definition":"CHECK (version_status = ANY (ARRAY['LOCAL_DRAFT'::text, 'VALIDATED_DRAFT'::text, 'BLOCKED_DRAFT'::text, 'PUBLISHED'::text, 'RETIRED'::text]))"}]},{"table":"template_studio_templates","schema":"public","columns":[{"name":"id","type":"bigint","default":null,"identity":"d","not_null":true,"generated":""},{"name":"template_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_template_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"domain","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"vertical","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lane","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lifecycle_status","type":"text","default":"'DRAFT'::text","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":"uid()","identity":"","not_null":false,"generated":""},{"name":"created_by_label","type":"text","default":"'GodMode'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_template_studio_templates_source","definition":"CREATE INDEX idx_template_studio_templates_source ON public.template_studio_templates USING btree (source_template_id)"},{"name":"idx_template_studio_templates_status","definition":"CREATE INDEX idx_template_studio_templates_status ON public.template_studio_templates USING btree (lifecycle_status)"},{"name":"template_studio_templates_pkey","definition":"CREATE UNIQUE INDEX template_studio_templates_pkey ON public.template_studio_templates USING btree (id)"},{"name":"template_studio_templates_template_key_key","definition":"CREATE UNIQUE INDEX template_studio_templates_template_key_key ON public.template_studio_templates USING btree (template_key)"}],"policies":[{"cmd":"ALL","qual":"can_manage_experience_studio()","roles":["authenticated"],"tablename":"template_studio_templates","permissive":"PERMISSIVE","policyname":"experience studio admins manage templates","schemaname":"public","with_check":"can_manage_experience_studio()"},{"cmd":"ALL","qual":"is_manager_pm_or_higher(uid(), NULL::uuid)","roles":["authenticated"],"tablename":"template_studio_templates","permissive":"PERMISSIVE","policyname":"template studio godmode all templates","schemaname":"public","with_check":"is_manager_pm_or_higher(uid(), NULL::uuid)"},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"template_studio_templates","permissive":"PERMISSIVE","policyname":"template studio platform admin insert templates","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"},{"cmd":"SELECT","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_templates","permissive":"PERMISSIVE","policyname":"template studio platform admin read templates","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_templates","permissive":"PERMISSIVE","policyname":"template studio platform admin update templates","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"}],"triggers":[],"constraints":[{"name":"template_studio_templates_lifecycle_status_check","definition":"CHECK (lifecycle_status = ANY (ARRAY['DRAFT'::text, 'ACTIVE'::text, 'RETIRED'::text]))"},{"name":"template_studio_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"template_studio_templates_template_key_key","definition":"UNIQUE (template_key)"}]},{"table":"template_studio_tenant_applications","schema":"public","columns":[{"name":"id","type":"bigint","default":null,"identity":"d","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_version_id","type":"bigint","default":null,"identity":"","not_null":true,"generated":""},{"name":"application_status","type":"text","default":"'STAGED'::text","identity":"","not_null":true,"generated":""},{"name":"apply_receipt","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"applied_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"applied_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"rolled_back_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"rolled_back_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"scope_type","type":"text","default":"'tenant'::text","identity":"","not_null":true,"generated":""},{"name":"scope_id","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_template_studio_applications_scope","definition":"CREATE INDEX idx_template_studio_applications_scope ON public.template_studio_tenant_applications USING btree (scope_type, scope_id, application_status)"},{"name":"idx_template_studio_applications_tenant","definition":"CREATE INDEX idx_template_studio_applications_tenant ON public.template_studio_tenant_applications USING btree (tenant_id, application_status)"},{"name":"template_studio_tenant_applic_tenant_id_template_version_id_key","definition":"CREATE UNIQUE INDEX template_studio_tenant_applic_tenant_id_template_version_id_key ON public.template_studio_tenant_applications USING btree (tenant_id, template_version_id)"},{"name":"template_studio_tenant_applications_pkey","definition":"CREATE UNIQUE INDEX template_studio_tenant_applications_pkey ON public.template_studio_tenant_applications USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"can_manage_experience_studio()","roles":["authenticated"],"tablename":"template_studio_tenant_applications","permissive":"PERMISSIVE","policyname":"experience studio admins manage applications","schemaname":"public","with_check":"can_manage_experience_studio()"},{"cmd":"ALL","qual":"is_manager_pm_or_higher(uid(), tenant_id)","roles":["authenticated"],"tablename":"template_studio_tenant_applications","permissive":"PERMISSIVE","policyname":"template studio godmode all applications","schemaname":"public","with_check":"is_manager_pm_or_higher(uid(), tenant_id)"},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"template_studio_tenant_applications","permissive":"PERMISSIVE","policyname":"template studio platform admin insert applications","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"},{"cmd":"SELECT","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_tenant_applications","permissive":"PERMISSIVE","policyname":"template studio platform admin read applications","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)","roles":["public"],"tablename":"template_studio_tenant_applications","permissive":"PERMISSIVE","policyname":"template studio platform admin update applications","schemaname":"public","with_check":"(lower(COALESCE((jwt() ->> 'email'::text), ''::text)) = 'info@knocklaunch.app'::text)"}],"triggers":[],"constraints":[{"name":"template_studio_tenant_applic_tenant_id_template_version_id_key","definition":"UNIQUE (tenant_id, template_version_id)"},{"name":"template_studio_tenant_applications_application_status_check","definition":"CHECK (application_status = ANY (ARRAY['STAGED'::text, 'APPLIED'::text, 'ROLLED_BACK'::text, 'RETIRED'::text]))"},{"name":"template_studio_tenant_applications_pkey","definition":"PRIMARY KEY (id)"},{"name":"template_studio_tenant_applications_scope_type_check","definition":"CHECK (scope_type = ANY (ARRAY['tenant'::text, 'god_mode'::text, 'admin'::text, 'platform'::text]))"},{"name":"template_studio_tenant_applications_template_version_id_fkey","definition":"FOREIGN KEY (template_version_id) REFERENCES template_studio_template_versions(id)"}]},{"table":"tenant_ad_analytics_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"utm_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_medium","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_campaign","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"utm_content","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"landing_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referrer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"session_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"tenant_ad_analytics_events_campaign_idx","definition":"CREATE INDEX tenant_ad_analytics_events_campaign_idx ON public.tenant_ad_analytics_events USING btree (tenant_org_id, utm_source, utm_campaign, utm_content, occurred_at DESC)"},{"name":"tenant_ad_analytics_events_pkey","definition":"CREATE UNIQUE INDEX tenant_ad_analytics_events_pkey ON public.tenant_ad_analytics_events USING btree (id)"},{"name":"tenant_ad_analytics_events_session_dedupe_idx","definition":"CREATE UNIQUE INDEX tenant_ad_analytics_events_session_dedupe_idx ON public.tenant_ad_analytics_events USING btree (tenant_org_id, event_type, session_key, COALESCE(utm_source, ''::text), COALESCE(utm_campaign, ''::text), COALESCE(utm_content, ''::text)) WHERE (session_key IS NOT NULL)"},{"name":"tenant_ad_analytics_events_tenant_time_idx","definition":"CREATE INDEX tenant_ad_analytics_events_tenant_time_idx ON public.tenant_ad_analytics_events USING btree (tenant_org_id, occurred_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"tenant_ad_analytics_events","permissive":"PERMISSIVE","policyname":"tenant members can read ad analytics","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"tenant_ad_analytics_events_event_type_check","definition":"CHECK (event_type = 'landing_view'::text)"},{"name":"tenant_ad_analytics_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_ad_analytics_events_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"tenant_compliance_profiles","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"brokerage_legal_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"broker_of_record","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"broker_license_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"team_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_disclaimer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_call_script","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"approved_sms_disclaimer","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"template_approval_required","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"campaign_approval_required","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"tenant_compliance_profiles_pkey","definition":"CREATE UNIQUE INDEX tenant_compliance_profiles_pkey ON public.tenant_compliance_profiles USING btree (id)"},{"name":"tenant_compliance_profiles_tenant_id_key","definition":"CREATE UNIQUE INDEX tenant_compliance_profiles_tenant_id_key ON public.tenant_compliance_profiles USING btree (tenant_id)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"tenant_compliance_profiles","permissive":"PERMISSIVE","policyname":"compliance_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tenant_compliance_profiles","permissive":"PERMISSIVE","policyname":"compliance_insert_owner","schemaname":"public","with_check":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())"},{"cmd":"SELECT","qual":"(is_tenant_member(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"tenant_compliance_profiles","permissive":"PERMISSIVE","policyname":"compliance_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())","roles":["authenticated"],"tablename":"tenant_compliance_profiles","permissive":"PERMISSIVE","policyname":"compliance_update_owner","schemaname":"public","with_check":"(is_tenant_owner(uid(), tenant_id) OR is_system_admin())"}],"triggers":[{"name":"trg_compliance_updated","definition":"CREATE TRIGGER trg_compliance_updated BEFORE UPDATE ON tenant_compliance_profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_compliance_profiles_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_compliance_profiles_tenant_id_key","definition":"UNIQUE (tenant_id)"}]},{"table":"tenant_content_integrity_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"content_table","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"content_row_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"scope_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"action_taken","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"details","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"tenant_content_integrity_events_pkey","definition":"CREATE UNIQUE INDEX tenant_content_integrity_events_pkey ON public.tenant_content_integrity_events USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tenant_content_integrity_events","permissive":"PERMISSIVE","policyname":"authenticated tenant users may record tenant content integrity ","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_content_integrity_events.tenant_org_id))))))"},{"cmd":"SELECT","qual":"(((tenant_org_id IS NULL) AND is_system_admin(uid())) OR ((tenant_org_id IS NOT NULL) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_content_integrity_events.tenant_org_id)))))))","roles":["authenticated"],"tablename":"tenant_content_integrity_events","permissive":"PERMISSIVE","policyname":"tenant content integrity events are admin-auditable","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"tenant_content_integrity_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_content_integrity_events_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE SET NULL"}]},{"table":"tenant_drive_folders","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"root_folder_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"templates_folder_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"agreements_folder_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"signed_agreements_folder_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"documents_folder_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"provisioned_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"provisioned_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"provisioning_status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"provisioning_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tenant_drive_folders_status","definition":"CREATE INDEX idx_tenant_drive_folders_status ON public.tenant_drive_folders USING btree (provisioning_status)"},{"name":"idx_tenant_drive_folders_tenant","definition":"CREATE INDEX idx_tenant_drive_folders_tenant ON public.tenant_drive_folders USING btree (tenant_id)"},{"name":"tenant_drive_folders_pkey","definition":"CREATE UNIQUE INDEX tenant_drive_folders_pkey ON public.tenant_drive_folders USING btree (id)"},{"name":"uq_tenant_drive_folder","definition":"CREATE UNIQUE INDEX uq_tenant_drive_folder ON public.tenant_drive_folders USING btree (tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = tenant_drive_folders.tenant_id))))","roles":["public"],"tablename":"tenant_drive_folders","permissive":"PERMISSIVE","policyname":"Users can view tenant folders","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenant_drive_folders","permissive":"PERMISSIVE","policyname":"platform_admin_manage_tenant_drive_folders","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"tenant_drive_folders_pkey","definition":"PRIMARY KEY (id)"},{"name":"uq_tenant_drive_folder","definition":"UNIQUE (tenant_id)"}]},{"table":"tenant_feature_entitlements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"feature_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"feature_entitlement_status","default":"'default'::feature_entitlement_status","identity":"","not_null":true,"generated":""},{"name":"source","type":"feature_entitlement_source","default":"'default'::feature_entitlement_source","identity":"","not_null":true,"generated":""},{"name":"plan_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"enabled_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"enabled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"disabled_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"disabled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tfe_feature","definition":"CREATE INDEX idx_tfe_feature ON public.tenant_feature_entitlements USING btree (feature_key)"},{"name":"idx_tfe_tenant","definition":"CREATE INDEX idx_tfe_tenant ON public.tenant_feature_entitlements USING btree (tenant_org_id)"},{"name":"tenant_feature_entitlements_pkey","definition":"CREATE UNIQUE INDEX tenant_feature_entitlements_pkey ON public.tenant_feature_entitlements USING btree (id)"},{"name":"tenant_feature_entitlements_tenant_org_id_feature_key_key","definition":"CREATE UNIQUE INDEX tenant_feature_entitlements_tenant_org_id_feature_key_key ON public.tenant_feature_entitlements USING btree (tenant_org_id, feature_key)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"tenant_feature_entitlements","permissive":"PERMISSIVE","policyname":"tfe system admin all","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"tenant_feature_entitlements","permissive":"PERMISSIVE","policyname":"tfe tenant members read","schemaname":"public","with_check":null}],"triggers":[{"name":"tfe_set_updated_at","definition":"CREATE TRIGGER tfe_set_updated_at BEFORE UPDATE ON tenant_feature_entitlements FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_feature_entitlements_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_feature_entitlements_tenant_org_id_feature_key_key","definition":"UNIQUE (tenant_org_id, feature_key)"}]},{"table":"tenant_mailboxes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":"'zoho_mail360'::text","identity":"","not_null":true,"generated":""},{"name":"account_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email_address","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mailbox_kind","type":"text","default":"'native'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"last_sync_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"tenant_mailboxes_account_key_idx","definition":"CREATE INDEX tenant_mailboxes_account_key_idx ON public.tenant_mailboxes USING btree (account_key)"},{"name":"tenant_mailboxes_one_default_per_tenant_idx","definition":"CREATE UNIQUE INDEX tenant_mailboxes_one_default_per_tenant_idx ON public.tenant_mailboxes USING btree (tenant_org_id) WHERE ((is_default = true) AND (status = 'active'::text))"},{"name":"tenant_mailboxes_pkey","definition":"CREATE UNIQUE INDEX tenant_mailboxes_pkey ON public.tenant_mailboxes USING btree (id)"},{"name":"tenant_mailboxes_tenant_org_id_account_key_key","definition":"CREATE UNIQUE INDEX tenant_mailboxes_tenant_org_id_account_key_key ON public.tenant_mailboxes USING btree (tenant_org_id, account_key)"},{"name":"tenant_mailboxes_tenant_status_idx","definition":"CREATE INDEX tenant_mailboxes_tenant_status_idx ON public.tenant_mailboxes USING btree (tenant_org_id, status)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"tenant_mailboxes","permissive":"PERMISSIVE","policyname":"tenant_mailboxes_member_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"tenant_mailboxes_mailbox_kind_check","definition":"CHECK (mailbox_kind = ANY (ARRAY['native'::text, 'sync'::text]))"},{"name":"tenant_mailboxes_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_mailboxes_provider_check","definition":"CHECK (provider = 'zoho_mail'::text)"},{"name":"tenant_mailboxes_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'setup_required'::text, 'disabled'::text, 'error'::text]))"},{"name":"tenant_mailboxes_tenant_org_id_account_key_key","definition":"UNIQUE (tenant_org_id, account_key)"},{"name":"tenant_mailboxes_tenant_org_id_fkey","definition":"FOREIGN KEY (tenant_org_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"tenant_media_assets","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"collection_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"bucket_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"original_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"derived_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"original_content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"derived_content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_kind","type":"text","default":"'upload'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'ready'::text","identity":"","not_null":true,"generated":""},{"name":"review_status","type":"text","default":"'unreviewed'::text","identity":"","not_null":true,"generated":""},{"name":"enhance_consent","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"enhancement_model","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"published","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"is_primary","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"enhanced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reviewed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"mime_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"size_bytes","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"storage_provider","type":"text","default":"'r2'::text","identity":"","not_null":true,"generated":""},{"name":"storage_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"tenant_media_assets_library_idx","definition":"CREATE INDEX tenant_media_assets_library_idx ON public.tenant_media_assets USING btree (tenant_id, collection_key, created_at DESC) WHERE (deleted_at IS NULL)"},{"name":"tenant_media_assets_pkey","definition":"CREATE UNIQUE INDEX tenant_media_assets_pkey ON public.tenant_media_assets USING btree (id)"},{"name":"tenant_media_assets_provider_idx","definition":"CREATE INDEX tenant_media_assets_provider_idx ON public.tenant_media_assets USING btree (storage_provider, bucket_name, storage_key) WHERE (deleted_at IS NULL)"},{"name":"tenant_media_assets_public_idx","definition":"CREATE INDEX tenant_media_assets_public_idx ON public.tenant_media_assets USING btree (tenant_id, collection_key, published) WHERE (published = true)"},{"name":"tenant_media_assets_singleton_primary_role_idx","definition":"CREATE UNIQUE INDEX tenant_media_assets_singleton_primary_role_idx ON public.tenant_media_assets USING btree (tenant_id, collection_key) WHERE ((is_primary = true) AND (deleted_at IS NULL) AND (collection_key = ANY (ARRAY['branding'::text, 'backgrounds'::text])))"},{"name":"tenant_media_assets_tenant_collection_idx","definition":"CREATE INDEX tenant_media_assets_tenant_collection_idx ON public.tenant_media_assets USING btree (tenant_id, collection_key, created_at DESC)"},{"name":"tenant_media_assets_tenant_id_bucket_name_original_key_key","definition":"CREATE UNIQUE INDEX tenant_media_assets_tenant_id_bucket_name_original_key_key ON public.tenant_media_assets USING btree (tenant_id, bucket_name, original_key)"}],"policies":[{"cmd":"DELETE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_media_assets.tenant_id)))))","roles":["authenticated"],"tablename":"tenant_media_assets","permissive":"PERMISSIVE","policyname":"tenant_media_assets_tenant_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tenant_media_assets","permissive":"PERMISSIVE","policyname":"tenant_media_assets_tenant_insert","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_media_assets.tenant_id)))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_media_assets.tenant_id)))))","roles":["authenticated"],"tablename":"tenant_media_assets","permissive":"PERMISSIVE","policyname":"tenant_media_assets_tenant_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_media_assets.tenant_id)))))","roles":["authenticated"],"tablename":"tenant_media_assets","permissive":"PERMISSIVE","policyname":"tenant_media_assets_tenant_update","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND (m.tenant_id = tenant_media_assets.tenant_id)))))"}],"triggers":[],"constraints":[{"name":"tenant_media_assets_active_audio_chk","definition":"CHECK (deleted_at IS NOT NULL OR lower(COALESCE(mime_type, ''::text)) !~~ 'audio/%'::text)"},{"name":"tenant_media_assets_created_by_fkey","definition":"FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL"},{"name":"tenant_media_assets_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_media_assets_review_status_check","definition":"CHECK (review_status = ANY (ARRAY['unreviewed'::text, 'pending'::text, 'approved'::text, 'rejected'::text]))"},{"name":"tenant_media_assets_reviewed_by_fkey","definition":"FOREIGN KEY (reviewed_by) REFERENCES users(id) ON DELETE SET NULL"},{"name":"tenant_media_assets_source_kind_check","definition":"CHECK (source_kind = ANY (ARRAY['upload'::text, 'existing'::text]))"},{"name":"tenant_media_assets_status_check","definition":"CHECK (status = ANY (ARRAY['ready'::text, 'enhancing'::text, 'pending_review'::text, 'failed'::text]))"},{"name":"tenant_media_assets_tenant_id_bucket_name_original_key_key","definition":"UNIQUE (tenant_id, bucket_name, original_key)"},{"name":"tenant_media_assets_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"tenant_messaging_settings","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":"'none'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'not_configured'::text","identity":"","not_null":true,"generated":""},{"name":"sms_enabled","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"email_enabled","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sending_domain","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"brand_registration_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"consent_required","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"configured_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"amd_unknown_treated_as_machine","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"voicemail_silence_drop_seconds","type":"integer","default":"7","identity":"","not_null":true,"generated":""},{"name":"voicemail_drop_requires_amd_unknown_or_timeout","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"rep_confirm_human_window_ms","type":"integer","default":"7000","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tms_tenant","definition":"CREATE INDEX idx_tms_tenant ON public.tenant_messaging_settings USING btree (tenant_id)"},{"name":"tenant_messaging_settings_pkey","definition":"CREATE UNIQUE INDEX tenant_messaging_settings_pkey ON public.tenant_messaging_settings USING btree (id)"},{"name":"tenant_messaging_settings_tenant_id_key","definition":"CREATE UNIQUE INDEX tenant_messaging_settings_tenant_id_key ON public.tenant_messaging_settings USING btree (tenant_id)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenant_messaging_settings","permissive":"PERMISSIVE","policyname":"tms_delete_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"tenant_messaging_settings","permissive":"PERMISSIVE","policyname":"tms_insert_owner","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_member((tenant_id)::text) OR is_system_admin(uid()))","roles":["public"],"tablename":"tenant_messaging_settings","permissive":"PERMISSIVE","policyname":"tms_select_members","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))","roles":["public"],"tablename":"tenant_messaging_settings","permissive":"PERMISSIVE","policyname":"tms_update_owner","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))"}],"triggers":[{"name":"trg_tms_updated_at","definition":"CREATE TRIGGER trg_tms_updated_at BEFORE UPDATE ON tenant_messaging_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_messaging_settings_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_messaging_settings_provider_check","definition":"CHECK (provider = ANY (ARRAY['none'::text, 'twilio'::text, 'other'::text]))"},{"name":"tenant_messaging_settings_status_check","definition":"CHECK (status = ANY (ARRAY['not_configured'::text, 'pending_setup'::text, 'active'::text, 'disabled'::text, 'rejected'::text]))"},{"name":"tenant_messaging_settings_tenant_id_key","definition":"UNIQUE (tenant_id)"}]},{"table":"tenant_outreach_send_attempts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"queue_item_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"campaign_property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"failure_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"provider_message_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tosa_queue_item","definition":"CREATE INDEX idx_tosa_queue_item ON public.tenant_outreach_send_attempts USING btree (queue_item_id)"},{"name":"idx_tosa_tenant_created","definition":"CREATE INDEX idx_tosa_tenant_created ON public.tenant_outreach_send_attempts USING btree (tenant_id, created_at DESC)"},{"name":"tenant_outreach_send_attempts_pkey","definition":"CREATE UNIQUE INDEX tenant_outreach_send_attempts_pkey ON public.tenant_outreach_send_attempts USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(is_tenant_member((tenant_id)::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"tenant_outreach_send_attempts","permissive":"PERMISSIVE","policyname":"tosa_select_members","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"tenant_outreach_send_attempts_channel_check","definition":"CHECK (channel = ANY (ARRAY['sms_preview'::text, 'email_preview'::text, 'sms'::text, 'email'::text]))"},{"name":"tenant_outreach_send_attempts_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_outreach_send_attempts_status_check","definition":"CHECK (status = ANY (ARRAY['blocked'::text, 'attempted'::text, 'sent'::text, 'failed'::text]))"}]},{"table":"tenant_phone_numbers","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"twilio_number_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"friendly_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"capabilities","type":"jsonb","default":"'{\"mms\": true, \"sms\": true, \"voice\": true}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tenant_phone_numbers_default","definition":"CREATE INDEX idx_tenant_phone_numbers_default ON public.tenant_phone_numbers USING btree (tenant_org_id, is_default) WHERE (is_default = true)"},{"name":"idx_tenant_phone_numbers_tenant","definition":"CREATE INDEX idx_tenant_phone_numbers_tenant ON public.tenant_phone_numbers USING btree (tenant_org_id)"},{"name":"tenant_phone_numbers_pkey","definition":"CREATE UNIQUE INDEX tenant_phone_numbers_pkey ON public.tenant_phone_numbers USING btree (id)"},{"name":"tenant_phone_numbers_unique_number","definition":"CREATE UNIQUE INDEX tenant_phone_numbers_unique_number ON public.tenant_phone_numbers USING btree (phone_number)"}],"policies":[{"cmd":"ALL","qual":"(is_platform_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = tenant_phone_numbers.tenant_org_id) AND (m.is_owner = true) AND (m.status = 'active'::text)))))","roles":["authenticated"],"tablename":"tenant_phone_numbers","permissive":"PERMISSIVE","policyname":"Owners and admins can manage tenant phone numbers","schemaname":"public","with_check":"(is_platform_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = tenant_phone_numbers.tenant_org_id) AND (m.is_owner = true) AND (m.status = 'active'::text)))))"},{"cmd":"SELECT","qual":"((tenant_org_id IN ( SELECT user_tenant_memberships.tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.status = 'active'::text)))) OR is_platform_admin(uid()))","roles":["authenticated"],"tablename":"tenant_phone_numbers","permissive":"PERMISSIVE","policyname":"Tenant members can read their phone numbers","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_tenant_phone_numbers_updated","definition":"CREATE TRIGGER trg_tenant_phone_numbers_updated BEFORE UPDATE ON tenant_phone_numbers FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_phone_numbers_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_phone_numbers_unique_number","definition":"UNIQUE (phone_number)"}]},{"table":"tenant_price_overrides","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"zip3","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"item_code","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"unit_price","type":"numeric(12,2)","default":null,"identity":"","not_null":true,"generated":""},{"name":"effective_date","type":"date","default":"CURRENT_DATE","identity":"","not_null":true,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tenant_price_overrides_lookup","definition":"CREATE INDEX idx_tenant_price_overrides_lookup ON public.tenant_price_overrides USING btree (tenant_org_id, zip3, item_code, effective_date DESC)"},{"name":"tenant_price_overrides_pkey","definition":"CREATE UNIQUE INDEX tenant_price_overrides_pkey ON public.tenant_price_overrides USING btree (id)"},{"name":"tenant_price_overrides_tenant_org_id_zip3_item_code_effecti_key","definition":"CREATE UNIQUE INDEX tenant_price_overrides_tenant_org_id_zip3_item_code_effecti_key ON public.tenant_price_overrides USING btree (tenant_org_id, zip3, item_code, effective_date)"}],"policies":[{"cmd":"DELETE","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"tenant_price_overrides","permissive":"PERMISSIVE","policyname":"tenant members delete price overrides","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tenant_price_overrides","permissive":"PERMISSIVE","policyname":"tenant members insert price overrides","schemaname":"public","with_check":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"tenant_price_overrides","permissive":"PERMISSIVE","policyname":"tenant members read price overrides","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(tenant_org_id IN ( SELECT m.tenant_id\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"tenant_price_overrides","permissive":"PERMISSIVE","policyname":"tenant members update price overrides","schemaname":"public","with_check":null}],"triggers":[{"name":"update_tenant_price_overrides_updated_at","definition":"CREATE TRIGGER update_tenant_price_overrides_updated_at BEFORE UPDATE ON tenant_price_overrides FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_price_overrides_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_price_overrides_tenant_org_id_zip3_item_code_effecti_key","definition":"UNIQUE (tenant_org_id, zip3, item_code, effective_date)"},{"name":"tenant_price_overrides_zip3_check","definition":"CHECK (length(zip3) = 3)"}]},{"table":"tenant_provider_credentials","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"credential_status","type":"text","default":"'missing'::text","identity":"","not_null":true,"generated":""},{"name":"credential_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"sending_domain","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"verification_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tpc_tenant","definition":"CREATE INDEX idx_tpc_tenant ON public.tenant_provider_credentials USING btree (tenant_id)"},{"name":"tenant_provider_credentials_pkey","definition":"CREATE UNIQUE INDEX tenant_provider_credentials_pkey ON public.tenant_provider_credentials USING btree (id)"},{"name":"tenant_provider_credentials_tenant_id_provider_key","definition":"CREATE UNIQUE INDEX tenant_provider_credentials_tenant_id_provider_key ON public.tenant_provider_credentials USING btree (tenant_id, provider)"}],"policies":[{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"tenant_provider_credentials","permissive":"PERMISSIVE","policyname":"tpc_delete_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tenant_provider_credentials","permissive":"PERMISSIVE","policyname":"tpc_insert_owner_admin","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))"},{"cmd":"SELECT","qual":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"tenant_provider_credentials","permissive":"PERMISSIVE","policyname":"tpc_select_owner_admin","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"tenant_provider_credentials","permissive":"PERMISSIVE","policyname":"tpc_update_owner_admin","schemaname":"public","with_check":"(is_tenant_owner_for(uid(), (tenant_id)::text) OR is_system_admin(uid()))"}],"triggers":[{"name":"trg_tpc_updated_at","definition":"CREATE TRIGGER trg_tpc_updated_at BEFORE UPDATE ON tenant_provider_credentials FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_provider_credentials_credential_status_check","definition":"CHECK (credential_status = ANY (ARRAY['missing'::text, 'pending'::text, 'active'::text, 'disabled'::text, 'invalid'::text]))"},{"name":"tenant_provider_credentials_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_provider_credentials_provider_check","definition":"CHECK (provider = ANY (ARRAY['twilio'::text, 'resend'::text, 'stripe'::text, 'square'::text, 'zoho_mail'::text, 'zoho_mail_admin'::text, 'google_workspace'::text, 'microsoft_365'::text, 'monday'::text, 'quickbooks'::text, 'slack'::text, 'dropbox'::text, 'hubspot'::text, 'docusign'::text, 'other'::text]))"},{"name":"tenant_provider_credentials_tenant_id_provider_key","definition":"UNIQUE (tenant_id, provider)"}]},{"table":"tenant_provider_oauth_states","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"state_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"return_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"code_verifier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"consumed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_tenant_provider_oauth_states_expiry","definition":"CREATE INDEX idx_tenant_provider_oauth_states_expiry ON public.tenant_provider_oauth_states USING btree (expires_at)"},{"name":"tenant_provider_oauth_states_pkey","definition":"CREATE UNIQUE INDEX tenant_provider_oauth_states_pkey ON public.tenant_provider_oauth_states USING btree (id)"},{"name":"tenant_provider_oauth_states_state_hash_key","definition":"CREATE UNIQUE INDEX tenant_provider_oauth_states_state_hash_key ON public.tenant_provider_oauth_states USING btree (state_hash)"}],"policies":[],"triggers":[],"constraints":[{"name":"tenant_provider_oauth_states_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_provider_oauth_states_provider_check","definition":"CHECK (provider = ANY (ARRAY['google_workspace'::text, 'microsoft_365'::text, 'monday'::text, 'quickbooks'::text, 'slack'::text, 'dropbox'::text, 'hubspot'::text, 'docusign'::text]))"},{"name":"tenant_provider_oauth_states_state_hash_key","definition":"UNIQUE (state_hash)"}]},{"table":"tenant_provider_secrets","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"provider","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"account_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ciphertext","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"iv","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"key_version","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"verification_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"tenant_provider_secrets_pkey","definition":"CREATE UNIQUE INDEX tenant_provider_secrets_pkey ON public.tenant_provider_secrets USING btree (id)"},{"name":"tenant_provider_secrets_tenant_id_provider_key","definition":"CREATE UNIQUE INDEX tenant_provider_secrets_tenant_id_provider_key ON public.tenant_provider_secrets USING btree (tenant_id, provider)"},{"name":"tenant_provider_secrets_tenant_provider_idx","definition":"CREATE INDEX tenant_provider_secrets_tenant_provider_idx ON public.tenant_provider_secrets USING btree (tenant_id, provider)"}],"policies":[],"triggers":[{"name":"trg_tenant_provider_secrets_updated_at","definition":"CREATE TRIGGER trg_tenant_provider_secrets_updated_at BEFORE UPDATE ON tenant_provider_secrets FOR EACH ROW EXECUTE FUNCTION tenant_provider_secrets_touch_updated_at()"}],"constraints":[{"name":"tenant_provider_secrets_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_provider_secrets_provider_check","definition":"CHECK (provider = ANY (ARRAY['twilio'::text, 'resend'::text, 'stripe'::text, 'square'::text, 'zoho_mail'::text, 'zoho_mail_admin'::text, 'google_workspace'::text, 'microsoft_365'::text, 'monday'::text, 'quickbooks'::text, 'slack'::text, 'dropbox'::text, 'hubspot'::text, 'docusign'::text]))"},{"name":"tenant_provider_secrets_tenant_id_provider_key","definition":"UNIQUE (tenant_id, provider)"}]},{"table":"tenant_readiness_checks","schema":"public","columns":[{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"check_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"detail","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"tenant_readiness_checks_pkey","definition":"CREATE UNIQUE INDEX tenant_readiness_checks_pkey ON public.tenant_readiness_checks USING btree (tenant_id, check_key)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = tenant_readiness_checks.tenant_id) AND (membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"tenant_readiness_checks","permissive":"PERMISSIVE","policyname":"tenant_readiness_checks_read","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"tenant_readiness_checks_pkey","definition":"PRIMARY KEY (tenant_id, check_key)"},{"name":"tenant_readiness_checks_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'ready'::text, 'needs_input'::text, 'blocked'::text, 'not_applicable'::text]))"},{"name":"tenant_readiness_checks_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"tenant_rebuttals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenancy_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"objection_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"short_rebuttal","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"normal_rebuttal","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"long_rebuttal","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'Other'::text","identity":"","not_null":true,"generated":""},{"name":"tags","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_template","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"derived_from_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"adopted_admin_version","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tenant_rebuttals_category","definition":"CREATE INDEX idx_tenant_rebuttals_category ON public.tenant_rebuttals USING btree (tenancy_type, category, order_index)"},{"name":"idx_tenant_rebuttals_derived","definition":"CREATE INDEX idx_tenant_rebuttals_derived ON public.tenant_rebuttals USING btree (derived_from_template_id)"},{"name":"idx_tenant_rebuttals_tenancy_type","definition":"CREATE INDEX idx_tenant_rebuttals_tenancy_type ON public.tenant_rebuttals USING btree (tenancy_type, order_index)"},{"name":"idx_tenant_rebuttals_tenant","definition":"CREATE INDEX idx_tenant_rebuttals_tenant ON public.tenant_rebuttals USING btree (tenant_org_id)"},{"name":"tenant_rebuttals_pkey","definition":"CREATE UNIQUE INDEX tenant_rebuttals_pkey ON public.tenant_rebuttals USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenant_rebuttals","permissive":"PERMISSIVE","policyname":"tenant_rebuttals_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(uid(), tenant_org_id))","roles":["public"],"tablename":"tenant_rebuttals","permissive":"PERMISSIVE","policyname":"tenant_rebuttals_tenant_member_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_org_id))","roles":["public"],"tablename":"tenant_rebuttals","permissive":"PERMISSIVE","policyname":"tenant_rebuttals_tenant_owner_manage","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), tenant_org_id))"}],"triggers":[{"name":"tenant_rebuttals_isolation_contract","definition":"CREATE TRIGGER tenant_rebuttals_isolation_contract BEFORE INSERT OR UPDATE OF tenant_org_id, tenancy_type, is_template, derived_from_template_id ON tenant_rebuttals FOR EACH ROW EXECUTE FUNCTION enforce_tenant_rebuttal_isolation()"},{"name":"tenant_rebuttals_updated_at","definition":"CREATE TRIGGER tenant_rebuttals_updated_at BEFORE UPDATE ON tenant_rebuttals FOR EACH ROW EXECUTE FUNCTION update_tenant_rebuttals_updated_at()"}],"constraints":[{"name":"tenant_rebuttals_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_rebuttals_tenancy_type_check","definition":"CHECK (tenancy_type = ANY (ARRAY['mitigation'::text, 'roofing'::text, 'public_adjuster'::text, 'realtor'::text]))"}]},{"table":"tenant_service_areas","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"zip_codes","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"neighborhoods","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"tenant_service_areas_pkey","definition":"CREATE UNIQUE INDEX tenant_service_areas_pkey ON public.tenant_service_areas USING btree (id)"},{"name":"tenant_service_areas_tenant_org_id_slug_key","definition":"CREATE UNIQUE INDEX tenant_service_areas_tenant_org_id_slug_key ON public.tenant_service_areas USING btree (tenant_org_id, slug)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = tenant_service_areas.tenant_org_id) AND (user_tenant_memberships.status = 'active'::text))))","roles":["authenticated"],"tablename":"tenant_service_areas","permissive":"PERMISSIVE","policyname":"Members can view service areas","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = tenant_service_areas.tenant_org_id) AND (user_tenant_memberships.status = 'active'::text) AND (user_tenant_memberships.is_owner = true))))","roles":["authenticated"],"tablename":"tenant_service_areas","permissive":"PERMISSIVE","policyname":"Owners can delete service areas","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"tenant_service_areas","permissive":"PERMISSIVE","policyname":"Owners can insert service areas","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = tenant_service_areas.tenant_org_id) AND (user_tenant_memberships.status = 'active'::text) AND (user_tenant_memberships.is_owner = true))))"},{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = tenant_service_areas.tenant_org_id) AND (user_tenant_memberships.status = 'active'::text) AND (user_tenant_memberships.is_owner = true))))","roles":["authenticated"],"tablename":"tenant_service_areas","permissive":"PERMISSIVE","policyname":"Owners can update service areas","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"tenant_service_areas_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_service_areas_tenant_org_id_slug_key","definition":"UNIQUE (tenant_org_id, slug)"}]},{"table":"tenant_subscriptions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"plan_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'trial'::text","identity":"","not_null":true,"generated":""},{"name":"trial_ends_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_period_start","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_period_end","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"paddle_subscription_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"paddle_customer_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"seat_count","type":"integer","default":"1","identity":"","not_null":true,"generated":""},{"name":"seat_overage","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"cancel_at_period_end","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"billing_cycle","type":"text","default":"'monthly'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"stripe_customer_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"stripe_subscription_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"stripe_price_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"stripe_environment","type":"text","default":"'sandbox'::text","identity":"","not_null":false,"generated":""},{"name":"cancel_at_period_end_synced_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tenant_subscriptions_status","definition":"CREATE INDEX idx_tenant_subscriptions_status ON public.tenant_subscriptions USING btree (status)"},{"name":"idx_tenant_subscriptions_tenant","definition":"CREATE INDEX idx_tenant_subscriptions_tenant ON public.tenant_subscriptions USING btree (tenant_id)"},{"name":"tenant_subscriptions_pkey","definition":"CREATE UNIQUE INDEX tenant_subscriptions_pkey ON public.tenant_subscriptions USING btree (id)"},{"name":"tenant_subscriptions_stripe_sub_idx","definition":"CREATE UNIQUE INDEX tenant_subscriptions_stripe_sub_idx ON public.tenant_subscriptions USING btree (stripe_subscription_id) WHERE (stripe_subscription_id IS NOT NULL)"},{"name":"tenant_subscriptions_tenant_id_key","definition":"CREATE UNIQUE INDEX tenant_subscriptions_tenant_id_key ON public.tenant_subscriptions USING btree (tenant_id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenant_subscriptions","permissive":"PERMISSIVE","policyname":"Only system admins modify subscriptions","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = tenant_subscriptions.tenant_id) AND (m.status = 'active'::text)))))","roles":["public"],"tablename":"tenant_subscriptions","permissive":"PERMISSIVE","policyname":"Tenant members read their subscription","schemaname":"public","with_check":null}],"triggers":[{"name":"update_tenant_subscriptions_updated_at","definition":"CREATE TRIGGER update_tenant_subscriptions_updated_at BEFORE UPDATE ON tenant_subscriptions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenant_subscriptions_billing_cycle_check","definition":"CHECK (billing_cycle = ANY (ARRAY['monthly'::text, 'annual'::text]))"},{"name":"tenant_subscriptions_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenant_subscriptions_status_check","definition":"CHECK (status = ANY (ARRAY['trial'::text, 'active'::text, 'past_due'::text, 'cancelled'::text, 'expired'::text, 'trial_expired'::text]))"},{"name":"tenant_subscriptions_tenant_id_key","definition":"UNIQUE (tenant_id)"}]},{"table":"tenant_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tenant_templates_tenant_type","definition":"CREATE INDEX idx_tenant_templates_tenant_type ON public.tenant_templates USING btree (tenant_type)"},{"name":"tenant_templates_name_key","definition":"CREATE UNIQUE INDEX tenant_templates_name_key ON public.tenant_templates USING btree (name)"},{"name":"tenant_templates_pkey","definition":"CREATE UNIQUE INDEX tenant_templates_pkey ON public.tenant_templates USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenant_templates","permissive":"PERMISSIVE","policyname":"platform_admin_manage_tenant_templates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"tenant_templates_name_key","definition":"UNIQUE (name)"},{"name":"tenant_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"tenants","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"owner_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"google_drive_root_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"master_registry_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"settings","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"drive_provisioned_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_provisioning_status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"drive_provisioning_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_slug","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"drive_map","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"company_legal_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_dba_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_logo_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"letterhead_config","type":"jsonb","default":"'{\"logo_size\": \"medium\", \"header_color\": \"hsl(var(--primary))\", \"show_tagline\": true, \"tagline_text\": \"\", \"logo_position\": \"left\"}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"company_email_domain","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_trial","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"trial_account_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_descriptor","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"realtor_license_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"realtor_license_state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"realtor_license_expires_at","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"secondary_color","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"disclaimer_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_facing_title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"branded_sender_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_website","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"company_mailing_address","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_tenants_is_trial","definition":"CREATE INDEX idx_tenants_is_trial ON public.tenants USING btree (is_trial) WHERE (is_trial = true)"},{"name":"idx_tenants_owner","definition":"CREATE INDEX idx_tenants_owner ON public.tenants USING btree (owner_id)"},{"name":"idx_tenants_status","definition":"CREATE INDEX idx_tenants_status ON public.tenants USING btree (status)"},{"name":"tenants_company_slug_unique","definition":"CREATE UNIQUE INDEX tenants_company_slug_unique ON public.tenants USING btree (company_slug) WHERE (company_slug IS NOT NULL)"},{"name":"tenants_pkey","definition":"CREATE UNIQUE INDEX tenants_pkey ON public.tenants USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"Authenticated users can create tenants","schemaname":"public","with_check":"((uid() IS NOT NULL) AND (owner_id = uid()))"},{"cmd":"UPDATE","qual":"(owner_id = uid())","roles":["authenticated"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"Owners can update their tenants","schemaname":"public","with_check":"(owner_id = uid())"},{"cmd":"SELECT","qual":"(id IN ( SELECT get_partner_tenant_ids() AS get_partner_tenant_ids))","roles":["authenticated"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"Users can view partner tenant names","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.tenant_id = tenants.id) AND (user_roles.user_id = uid()))))","roles":["public"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"Users can view their tenants via roles","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"platform_admin_delete_tenants","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"platform_admin_update_tenants","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"tenants","permissive":"PERMISSIVE","policyname":"platform_admin_view_tenants","schemaname":"public","with_check":null}],"triggers":[{"name":"tenants_normalize_logo_ingest_base64","definition":"CREATE TRIGGER tenants_normalize_logo_ingest_base64 BEFORE INSERT OR UPDATE OF settings ON tenants FOR EACH ROW EXECUTE FUNCTION normalize_tenant_logo_ingest_base64()"},{"name":"trg_seed_default_automation_on_tenant_create","definition":"CREATE TRIGGER trg_seed_default_automation_on_tenant_create AFTER INSERT ON tenants FOR EACH ROW EXECUTE FUNCTION seed_default_automation_on_tenant_create()"},{"name":"trg_seed_roofing_invoice_templates","definition":"CREATE TRIGGER trg_seed_roofing_invoice_templates AFTER INSERT ON tenants FOR EACH ROW EXECUTE FUNCTION seed_roofing_invoice_templates()"},{"name":"update_tenants_updated_at","definition":"CREATE TRIGGER update_tenants_updated_at BEFORE UPDATE ON tenants FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"tenants_pkey","definition":"PRIMARY KEY (id)"},{"name":"tenants_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'inactive'::text, 'suspended'::text, 'archived'::text]))"},{"name":"tenants_tenant_type_check","definition":"CHECK (tenant_type = ANY (ARRAY['MITIGATION'::text, 'ROOFING_COMPANY'::text, 'PUBLIC_ADJUSTER_FIRM'::text, 'REALTOR'::text, 'LAWN_CARE'::text, 'TIRE_SHOP'::text, 'AUTO_DETAILING'::text, 'CAFE_QSR'::text, 'MOBILE_VENDOR'::text, 'SHORT_TERM_RENTAL'::text, 'MISC'::text]))"}]},{"table":"territories","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"polygon_geojson","type":"jsonb","default":null,"identity":"","not_null":true,"generated":""},{"name":"color","type":"text","default":"'#3b82f6'::text","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_territories_tenant","definition":"CREATE INDEX idx_territories_tenant ON public.territories USING btree (tenant_org_id)"},{"name":"territories_pkey","definition":"CREATE UNIQUE INDEX territories_pkey ON public.territories USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM (security_active_user_tenant_memberships utm\n     JOIN user_roles ur ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((utm.user_id = uid()) AND (ur.role = ANY (ARRAY['Admin'::app_role, 'Owner'::app_role, 'GodMode'::app_role])))))","roles":["public"],"tablename":"territories","permissive":"PERMISSIVE","policyname":"Admins can manage territories","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"territories","permissive":"PERMISSIVE","policyname":"Users can view territories in their tenant","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"territories","permissive":"PERMISSIVE","policyname":"Users view tenant territories","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"territories","permissive":"PERMISSIVE","policyname":"platform_admin_manage_territories","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["public"],"tablename":"territories","permissive":"PERMISSIVE","policyname":"ter_all","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"territories_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"territory_analytics","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"territory_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"calculated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"time_range","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"visit_density","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"conversion_rate","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"roi_score","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"saturation_level","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"hot_zones","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommendations","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"metrics","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_territory_analytics_territory","definition":"CREATE INDEX idx_territory_analytics_territory ON public.territory_analytics USING btree (territory_id)"},{"name":"territory_analytics_pkey","definition":"CREATE UNIQUE INDEX territory_analytics_pkey ON public.territory_analytics USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = territory_analytics.tenant_org_id))))","roles":["public"],"tablename":"territory_analytics","permissive":"PERMISSIVE","policyname":"Tenant members view territory analytics","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"territory_analytics_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"territory_assignments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"territory_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_territory_assignments_tenant","definition":"CREATE INDEX idx_territory_assignments_tenant ON public.territory_assignments USING btree (tenant_org_id)"},{"name":"idx_territory_assignments_territory","definition":"CREATE INDEX idx_territory_assignments_territory ON public.territory_assignments USING btree (territory_id)"},{"name":"idx_territory_assignments_user","definition":"CREATE INDEX idx_territory_assignments_user ON public.territory_assignments USING btree (user_id)"},{"name":"territory_assignments_pkey","definition":"CREATE UNIQUE INDEX territory_assignments_pkey ON public.territory_assignments USING btree (id)"},{"name":"territory_assignments_territory_id_user_id_key","definition":"CREATE UNIQUE INDEX territory_assignments_territory_id_user_id_key ON public.territory_assignments USING btree (territory_id, user_id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM (security_active_user_tenant_memberships utm\n     JOIN user_roles ur ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((utm.user_id = uid()) AND (ur.role = ANY (ARRAY['Admin'::app_role, 'Owner'::app_role, 'GodMode'::app_role])))))","roles":["public"],"tablename":"territory_assignments","permissive":"PERMISSIVE","policyname":"Admins can manage territory assignments","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((user_id = uid()) OR (tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM (security_active_user_tenant_memberships utm\n     JOIN user_roles ur ON (((ur.user_id = utm.user_id) AND (ur.tenant_id = utm.tenant_id))))\n  WHERE ((utm.user_id = uid()) AND (ur.role = ANY (ARRAY['Admin'::app_role, 'Owner'::app_role, 'GodMode'::app_role]))))))","roles":["public"],"tablename":"territory_assignments","permissive":"PERMISSIVE","policyname":"Users can view their territory assignments","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"territory_assignments","permissive":"PERMISSIVE","policyname":"Users view tenant assignments","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"territory_assignments","permissive":"PERMISSIVE","policyname":"platform_admin_manage_territory_assignments","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[],"constraints":[{"name":"territory_assignments_pkey","definition":"PRIMARY KEY (id)"},{"name":"territory_assignments_territory_id_user_id_key","definition":"UNIQUE (territory_id, user_id)"}]},{"table":"test_account_audit","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"performed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"test_account_audit_pkey","definition":"CREATE UNIQUE INDEX test_account_audit_pkey ON public.test_account_audit USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"test_account_audit","permissive":"PERMISSIVE","policyname":"test_account_audit_insert_authenticated","schemaname":"public","with_check":"true"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(tenant_org_id) OR is_system_admin())","roles":["authenticated"],"tablename":"test_account_audit","permissive":"PERMISSIVE","policyname":"test_account_audit_tenant_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"test_account_audit_action_check","definition":"CHECK (action = ANY (ARRAY['marked'::text, 'unmarked'::text, 'static_seeded'::text, 'static_attempted_modify'::text, 'static_attempted_delete'::text]))"},{"name":"test_account_audit_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"trial_accounts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"client_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"market_state","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"market_county","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"trial_status","type":"text","default":"'active'::text","identity":"","not_null":true,"generated":""},{"name":"trial_start_date","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"trial_end_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"allowed_regions","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"allowed_counties","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"allowed_zip_codes","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"allowed_map_bounds","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"county_polygon_geojson","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"default_center","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"converted_to_full_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"converted_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"feature_overrides","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_trial_accounts_status","definition":"CREATE INDEX idx_trial_accounts_status ON public.trial_accounts USING btree (trial_status)"},{"name":"idx_trial_accounts_tenant","definition":"CREATE INDEX idx_trial_accounts_tenant ON public.trial_accounts USING btree (tenant_id)"},{"name":"trial_accounts_pkey","definition":"CREATE UNIQUE INDEX trial_accounts_pkey ON public.trial_accounts USING btree (id)"},{"name":"trial_accounts_tenant_id_key","definition":"CREATE UNIQUE INDEX trial_accounts_tenant_id_key ON public.trial_accounts USING btree (tenant_id)"}],"policies":[{"cmd":"DELETE","qual":"is_global_admin(uid())","roles":["authenticated"],"tablename":"trial_accounts","permissive":"PERMISSIVE","policyname":"trial_accounts_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"trial_accounts","permissive":"PERMISSIVE","policyname":"trial_accounts_admin_insert","schemaname":"public","with_check":"is_global_admin(uid())"},{"cmd":"UPDATE","qual":"is_global_admin(uid())","roles":["authenticated"],"tablename":"trial_accounts","permissive":"PERMISSIVE","policyname":"trial_accounts_admin_update","schemaname":"public","with_check":"is_global_admin(uid())"},{"cmd":"SELECT","qual":"(is_global_admin(uid()) OR is_tenant_member(uid(), tenant_id))","roles":["authenticated"],"tablename":"trial_accounts","permissive":"PERMISSIVE","policyname":"trial_accounts_select","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_sync_tenant_is_trial","definition":"CREATE TRIGGER trg_sync_tenant_is_trial AFTER INSERT OR DELETE ON trial_accounts FOR EACH ROW EXECUTE FUNCTION sync_tenant_is_trial()"},{"name":"trg_trial_accounts_updated_at","definition":"CREATE TRIGGER trg_trial_accounts_updated_at BEFORE UPDATE ON trial_accounts FOR EACH ROW EXECUTE FUNCTION touch_trial_accounts_updated_at()"}],"constraints":[{"name":"trial_accounts_pkey","definition":"PRIMARY KEY (id)"},{"name":"trial_accounts_tenant_id_key","definition":"UNIQUE (tenant_id)"},{"name":"trial_accounts_trial_status_check","definition":"CHECK (trial_status = ANY (ARRAY['active'::text, 'expired'::text, 'disabled'::text]))"}]},{"table":"trial_aha_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"parcels_scanned","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"permits_found","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"aging_roofs_found","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"storms_found","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"scan_payload","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"shown_to_user_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"trial_aha_runs_pkey","definition":"CREATE UNIQUE INDEX trial_aha_runs_pkey ON public.trial_aha_runs USING btree (id)"},{"name":"trial_aha_runs_tenant_id_key","definition":"CREATE UNIQUE INDEX trial_aha_runs_tenant_id_key ON public.trial_aha_runs USING btree (tenant_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"trial_aha_runs","permissive":"PERMISSIVE","policyname":"Only system admins insert aha runs","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = trial_aha_runs.tenant_id) AND (m.status = 'active'::text))))","roles":["public"],"tablename":"trial_aha_runs","permissive":"PERMISSIVE","policyname":"Tenant members can mark aha run shown","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = trial_aha_runs.tenant_id) AND (m.status = 'active'::text)))))","roles":["public"],"tablename":"trial_aha_runs","permissive":"PERMISSIVE","policyname":"Tenant members read their aha run","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"trial_aha_runs_pkey","definition":"PRIMARY KEY (id)"},{"name":"trial_aha_runs_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'running'::text, 'completed'::text, 'failed'::text]))"},{"name":"trial_aha_runs_tenant_id_key","definition":"UNIQUE (tenant_id)"}]},{"table":"trial_lifecycle_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"subscription_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"milestone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"trial_lifecycle_events_pkey","definition":"CREATE UNIQUE INDEX trial_lifecycle_events_pkey ON public.trial_lifecycle_events USING btree (id)"},{"name":"trial_lifecycle_events_sub_idx","definition":"CREATE INDEX trial_lifecycle_events_sub_idx ON public.trial_lifecycle_events USING btree (subscription_id)"},{"name":"trial_lifecycle_events_unique","definition":"CREATE UNIQUE INDEX trial_lifecycle_events_unique ON public.trial_lifecycle_events USING btree (subscription_id, milestone)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"trial_lifecycle_events","permissive":"PERMISSIVE","policyname":"Admins can read trial lifecycle events","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"trial_lifecycle_events_pkey","definition":"PRIMARY KEY (id)"},{"name":"trial_lifecycle_events_unique","definition":"UNIQUE (subscription_id, milestone)"}]},{"table":"ui_table_configs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"module","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"columns","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"sort","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"density","type":"text","default":"'comfortable'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_ui_table_configs_module","definition":"CREATE INDEX idx_ui_table_configs_module ON public.ui_table_configs USING btree (module)"},{"name":"idx_ui_table_configs_user_tenant","definition":"CREATE INDEX idx_ui_table_configs_user_tenant ON public.ui_table_configs USING btree (user_id, tenant_org_id)"},{"name":"ui_table_configs_pkey","definition":"CREATE UNIQUE INDEX ui_table_configs_pkey ON public.ui_table_configs USING btree (id)"},{"name":"ui_table_configs_user_id_tenant_org_id_module_key","definition":"CREATE UNIQUE INDEX ui_table_configs_user_id_tenant_org_id_module_key ON public.ui_table_configs USING btree (user_id, tenant_org_id, module)"}],"policies":[{"cmd":"DELETE","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = ui_table_configs.tenant_org_id)))))","roles":["public"],"tablename":"ui_table_configs","permissive":"PERMISSIVE","policyname":"Users can delete own configs in their tenants","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"ui_table_configs","permissive":"PERMISSIVE","policyname":"Users can insert own configs in their tenants","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = ui_table_configs.tenant_org_id)))))"},{"cmd":"UPDATE","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = ui_table_configs.tenant_org_id)))))","roles":["public"],"tablename":"ui_table_configs","permissive":"PERMISSIVE","policyname":"Users can update own configs in their tenants","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND (user_tenant_memberships.tenant_id = ui_table_configs.tenant_org_id)))))","roles":["public"],"tablename":"ui_table_configs","permissive":"PERMISSIVE","policyname":"Users can view own configs in their tenants","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"ui_table_configs_density_check","definition":"CHECK (density = ANY (ARRAY['compact'::text, 'comfortable'::text, 'spacious'::text]))"},{"name":"ui_table_configs_module_check","definition":"CHECK (module = ANY (ARRAY['contacts'::text, 'leads'::text, 'jobs'::text, 'invoices'::text]))"},{"name":"ui_table_configs_pkey","definition":"PRIMARY KEY (id)"},{"name":"ui_table_configs_user_id_tenant_org_id_module_key","definition":"UNIQUE (user_id, tenant_org_id, module)"}]},{"table":"unified_contacts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"first_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address2","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address3","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"address4","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"state","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"zip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"carrier_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number2","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number3","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"policy_number4","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number2","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number3","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_number4","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dol","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"second_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_claim_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"adjuster_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_estimator","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimator_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"roof_age","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"estimate_status","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"job_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"salesperson_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"work_classification","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_rep","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_user","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_date","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_time","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes2","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes3","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes4","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"additional_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"last_contact","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_touched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"priority","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"deleted_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"deletion_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_data","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"permit_scanned_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"has_recent_roof_permit","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"roof_permit_finaled_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"jobs_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"property_square_feet","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_parcel_id","type":"character varying(100)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data_fetched_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_owner_name","type":"character varying(255)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_assessed_value","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_bedrooms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_bathrooms","type":"numeric(3,1)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_year_built","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_lot_size","type":"numeric(10,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data_jurisdiction","type":"character varying(100)","default":null,"identity":"","not_null":false,"generated":""},{"name":"normalized_phone","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"normalized_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"normalized_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_tags","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"quality_score","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_ref","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_data_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_zoning","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_land_use","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_market_value","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_tax_amount","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_last_sale_date","type":"date","default":null,"identity":"","not_null":false,"generated":""},{"name":"property_last_sale_price","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_stage","type":"text","default":"'New / Unassigned'::text","identity":"","not_null":false,"generated":""},{"name":"graduated_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"lat","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"lng","type":"double precision","default":null,"identity":"","not_null":false,"generated":""},{"name":"geocoded_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"geocode_confidence","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"lost_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"engagement_score","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"recency_score","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_served_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"data_quality_flags","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"partner_types","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"referral_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"referral_partner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"portal_token","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"link_group_id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":false,"generated":""},{"name":"is_dnc","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"dnc_checked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"dnc_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_origin","type":"text","default":"'system'::text","identity":"","not_null":true,"generated":""},{"name":"created_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"legacy_lead_deck_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"deletion_reason_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_attempt_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"last_voicemail_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"last_voicemail_outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_callback_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"booking_rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"booked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_starts_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"gcal_event_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_outcome_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"appt_outcome_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"confirmation_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reminder_24h_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reminder_1h_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_notified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"lane_state","type":"lead_lane_state","default":"'cold'::lead_lane_state","identity":"","not_null":true,"generated":""},{"name":"source_batch_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_batch_row_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_source_ids","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"additional_phones","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"additional_emails","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"homeowner_attributes","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_created_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"secondary_owner_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"import_source","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"compliance_metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"insurance_carrier","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_filed_date","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_test_account","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"test_account_static","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"test_account_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"test_account_marked_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"test_account_marked_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"route_contact_number","type":"text","default":"lpad(((((10000000)::double precision + floor((random() * (90000000)::double precision))))::bigint)::text, 8, '0'::text)","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_contacts_assigned_deleted","definition":"CREATE INDEX idx_contacts_assigned_deleted ON public.unified_contacts USING btree (assigned_to, deleted_at)"},{"name":"idx_contacts_created_priority","definition":"CREATE INDEX idx_contacts_created_priority ON public.unified_contacts USING btree (created_at DESC, priority)"},{"name":"idx_contacts_quality_score","definition":"CREATE INDEX idx_contacts_quality_score ON public.unified_contacts USING btree (quality_score DESC) WHERE (quality_score IS NOT NULL)"},{"name":"idx_contacts_search","definition":"CREATE INDEX idx_contacts_search ON public.unified_contacts USING gin (to_tsvector('english'::regconfig, ((((((((((COALESCE(name, ''::text) || ' '::text) || COALESCE(email, ''::text)) || ' '::text) || COALESCE(phone, ''::text)) || ' '::text) || COALESCE(address, ''::text)) || ' '::text) || COALESCE(city, ''::text)) || ' '::text) || COALESCE(notes, ''::text))))"},{"name":"idx_contacts_tenant_status","definition":"CREATE INDEX idx_contacts_tenant_status ON public.unified_contacts USING btree (tenant_org_id, status)"},{"name":"idx_uc_appt_outcome","definition":"CREATE INDEX idx_uc_appt_outcome ON public.unified_contacts USING btree (appt_outcome) WHERE (appt_outcome IS NOT NULL)"},{"name":"idx_uc_appt_starts","definition":"CREATE INDEX idx_uc_appt_starts ON public.unified_contacts USING btree (appt_starts_at) WHERE (appt_starts_at IS NOT NULL)"},{"name":"idx_uc_booking_rep","definition":"CREATE INDEX idx_uc_booking_rep ON public.unified_contacts USING btree (booking_rep_id) WHERE (booking_rep_id IS NOT NULL)"},{"name":"idx_unified_contacts_active_tenant_updated","definition":"CREATE INDEX idx_unified_contacts_active_tenant_updated ON public.unified_contacts USING btree (tenant_org_id, updated_at DESC) WHERE ((deleted_at IS NULL) AND (archived_at IS NULL) AND (graduated_at IS NULL))"},{"name":"idx_unified_contacts_additional_phones","definition":"CREATE INDEX idx_unified_contacts_additional_phones ON public.unified_contacts USING gin (additional_phones)"},{"name":"idx_unified_contacts_assigned_to","definition":"CREATE INDEX idx_unified_contacts_assigned_to ON public.unified_contacts USING btree (assigned_to)"},{"name":"idx_unified_contacts_claim_stage","definition":"CREATE INDEX idx_unified_contacts_claim_stage ON public.unified_contacts USING btree (claim_stage) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_compliance_metadata_gin","definition":"CREATE INDEX idx_unified_contacts_compliance_metadata_gin ON public.unified_contacts USING gin (compliance_metadata) WHERE (compliance_metadata IS NOT NULL)"},{"name":"idx_unified_contacts_coordinates","definition":"CREATE INDEX idx_unified_contacts_coordinates ON public.unified_contacts USING btree (lat, lng) WHERE ((lat IS NOT NULL) AND (lng IS NOT NULL))"},{"name":"idx_unified_contacts_created_at","definition":"CREATE INDEX idx_unified_contacts_created_at ON public.unified_contacts USING btree (created_at DESC)"},{"name":"idx_unified_contacts_created_by_user_id","definition":"CREATE INDEX idx_unified_contacts_created_by_user_id ON public.unified_contacts USING btree (created_by_user_id) WHERE ((deleted_at IS NULL) AND (created_by_user_id IS NOT NULL))"},{"name":"idx_unified_contacts_deleted_at","definition":"CREATE INDEX idx_unified_contacts_deleted_at ON public.unified_contacts USING btree (deleted_at) WHERE (deleted_at IS NOT NULL)"},{"name":"idx_unified_contacts_external_source_ids","definition":"CREATE INDEX idx_unified_contacts_external_source_ids ON public.unified_contacts USING gin (external_source_ids)"},{"name":"idx_unified_contacts_import_source","definition":"CREATE INDEX idx_unified_contacts_import_source ON public.unified_contacts USING btree (tenant_org_id, import_source) WHERE (import_source IS NOT NULL)"},{"name":"idx_unified_contacts_is_dnc","definition":"CREATE INDEX idx_unified_contacts_is_dnc ON public.unified_contacts USING btree (is_dnc) WHERE (is_dnc = false)"},{"name":"idx_unified_contacts_jobs_stage","definition":"CREATE INDEX idx_unified_contacts_jobs_stage ON public.unified_contacts USING btree (jobs_stage) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_last_served_at","definition":"CREATE INDEX idx_unified_contacts_last_served_at ON public.unified_contacts USING btree (tenant_org_id, last_served_at NULLS FIRST) WHERE ((deleted_at IS NULL) AND (graduated_at IS NULL))"},{"name":"idx_unified_contacts_last_touched_at","definition":"CREATE INDEX idx_unified_contacts_last_touched_at ON public.unified_contacts USING btree (last_touched_at DESC)"},{"name":"idx_unified_contacts_lead_id","definition":"CREATE INDEX idx_unified_contacts_lead_id ON public.unified_contacts USING btree (lead_id)"},{"name":"idx_unified_contacts_lead_origin","definition":"CREATE INDEX idx_unified_contacts_lead_origin ON public.unified_contacts USING btree (lead_origin) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_lead_stage","definition":"CREATE INDEX idx_unified_contacts_lead_stage ON public.unified_contacts USING btree (lead_stage) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_legacy_lead_deck_id","definition":"CREATE INDEX idx_unified_contacts_legacy_lead_deck_id ON public.unified_contacts USING btree (legacy_lead_deck_id) WHERE (legacy_lead_deck_id IS NOT NULL)"},{"name":"idx_unified_contacts_norm_addr","definition":"CREATE INDEX idx_unified_contacts_norm_addr ON public.unified_contacts USING btree (tenant_org_id, normalize_address(address, zip)) WHERE (address IS NOT NULL)"},{"name":"idx_unified_contacts_normalized_address","definition":"CREATE INDEX idx_unified_contacts_normalized_address ON public.unified_contacts USING btree (normalized_address)"},{"name":"idx_unified_contacts_normalized_email","definition":"CREATE INDEX idx_unified_contacts_normalized_email ON public.unified_contacts USING btree (normalized_email)"},{"name":"idx_unified_contacts_normalized_phone","definition":"CREATE INDEX idx_unified_contacts_normalized_phone ON public.unified_contacts USING btree (normalized_phone)"},{"name":"idx_unified_contacts_partner_types","definition":"CREATE INDEX idx_unified_contacts_partner_types ON public.unified_contacts USING gin (partner_types)"},{"name":"idx_unified_contacts_permit_scan","definition":"CREATE INDEX idx_unified_contacts_permit_scan ON public.unified_contacts USING btree (permit_scanned_at)"},{"name":"idx_unified_contacts_phone_email","definition":"CREATE INDEX idx_unified_contacts_phone_email ON public.unified_contacts USING btree (phone, email) WHERE ((deleted_at IS NULL) AND (phone IS NOT NULL) AND (email IS NOT NULL))"},{"name":"idx_unified_contacts_property_fetched","definition":"CREATE INDEX idx_unified_contacts_property_fetched ON public.unified_contacts USING btree (property_data_fetched_at)"},{"name":"idx_unified_contacts_property_parcel","definition":"CREATE INDEX idx_unified_contacts_property_parcel ON public.unified_contacts USING btree (property_parcel_id)"},{"name":"idx_unified_contacts_quality_flags","definition":"CREATE INDEX idx_unified_contacts_quality_flags ON public.unified_contacts USING gin (data_quality_flags)"},{"name":"idx_unified_contacts_recent_roof","definition":"CREATE INDEX idx_unified_contacts_recent_roof ON public.unified_contacts USING btree (has_recent_roof_permit) WHERE (has_recent_roof_permit = true)"},{"name":"idx_unified_contacts_ref","definition":"CREATE INDEX idx_unified_contacts_ref ON public.unified_contacts USING btree (contact_ref)"},{"name":"idx_unified_contacts_referral","definition":"CREATE INDEX idx_unified_contacts_referral ON public.unified_contacts USING btree (referral_source) WHERE (referral_source IS NOT NULL)"},{"name":"idx_unified_contacts_secondary_owner_name","definition":"CREATE INDEX idx_unified_contacts_secondary_owner_name ON public.unified_contacts USING btree (lower(secondary_owner_name)) WHERE (secondary_owner_name IS NOT NULL)"},{"name":"idx_unified_contacts_source_batch","definition":"CREATE INDEX idx_unified_contacts_source_batch ON public.unified_contacts USING btree (source_batch_id)"},{"name":"idx_unified_contacts_status","definition":"CREATE INDEX idx_unified_contacts_status ON public.unified_contacts USING btree (status)"},{"name":"idx_unified_contacts_tenant_assigned","definition":"CREATE INDEX idx_unified_contacts_tenant_assigned ON public.unified_contacts USING btree (tenant_org_id, assigned_to) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_tenant_claim_number","definition":"CREATE INDEX idx_unified_contacts_tenant_claim_number ON public.unified_contacts USING btree (tenant_org_id, claim_number) WHERE ((claim_number IS NOT NULL) AND (deleted_at IS NULL))"},{"name":"idx_unified_contacts_tenant_insurance_carrier","definition":"CREATE INDEX idx_unified_contacts_tenant_insurance_carrier ON public.unified_contacts USING btree (tenant_org_id, insurance_carrier) WHERE ((insurance_carrier IS NOT NULL) AND (deleted_at IS NULL))"},{"name":"idx_unified_contacts_tenant_lead_score","definition":"CREATE INDEX idx_unified_contacts_tenant_lead_score ON public.unified_contacts USING btree (tenant_org_id, lead_score DESC NULLS LAST) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_tenant_org","definition":"CREATE INDEX idx_unified_contacts_tenant_org ON public.unified_contacts USING btree (tenant_org_id) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_tenant_org_id","definition":"CREATE INDEX idx_unified_contacts_tenant_org_id ON public.unified_contacts USING btree (tenant_org_id)"},{"name":"idx_unified_contacts_tenant_pipelines","definition":"CREATE INDEX idx_unified_contacts_tenant_pipelines ON public.unified_contacts USING btree (tenant_org_id, jobs_stage, claim_stage) WHERE (deleted_at IS NULL)"},{"name":"idx_unified_contacts_tenant_policy_number","definition":"CREATE INDEX idx_unified_contacts_tenant_policy_number ON public.unified_contacts USING btree (tenant_org_id, policy_number) WHERE ((policy_number IS NOT NULL) AND (deleted_at IS NULL))"},{"name":"idx_unified_contacts_tenant_state_present","definition":"CREATE INDEX idx_unified_contacts_tenant_state_present ON public.unified_contacts USING btree (tenant_org_id, state) WHERE (state IS NOT NULL)"},{"name":"idx_unified_contacts_test_account","definition":"CREATE INDEX idx_unified_contacts_test_account ON public.unified_contacts USING btree (tenant_org_id) WHERE (is_test_account = true)"},{"name":"unified_contacts_contact_id_key","definition":"CREATE UNIQUE INDEX unified_contacts_contact_id_key ON public.unified_contacts USING btree (contact_id)"},{"name":"unified_contacts_lane_state_idx","definition":"CREATE INDEX unified_contacts_lane_state_idx ON public.unified_contacts USING btree (tenant_org_id, lane_state)"},{"name":"unified_contacts_pkey","definition":"CREATE UNIQUE INDEX unified_contacts_pkey ON public.unified_contacts USING btree (id)"},{"name":"unified_contacts_tenant_route_contact_number_uidx","definition":"CREATE UNIQUE INDEX unified_contacts_tenant_route_contact_number_uidx ON public.unified_contacts USING btree (tenant_org_id, route_contact_number) WHERE ((tenant_org_id IS NOT NULL) AND (route_contact_number IS NOT NULL) AND (deleted_at IS NULL))"}],"policies":[{"cmd":"ALL","qual":"(((tenant_org_id IS NOT NULL) AND (tenant_org_id ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'::text) AND ((tenant_org_id)::uuid = ANY (COALESCE(( SELECT current_user_tenant_ids() AS current_user_tenant_ids), ARRAY[]::uuid[])))) OR ( SELECT is_system_admin(uid()) AS is_system_admin))","roles":["authenticated"],"tablename":"unified_contacts","permissive":"PERMISSIVE","policyname":"tenant_members_all_contacts","schemaname":"public","with_check":"(((tenant_org_id IS NOT NULL) AND (tenant_org_id ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'::text) AND ((tenant_org_id)::uuid = ANY (COALESCE(( SELECT current_user_tenant_ids() AS current_user_tenant_ids), ARRAY[]::uuid[])))) OR ( SELECT is_system_admin(uid()) AS is_system_admin))"},{"cmd":"SELECT","qual":"(((tenant_org_id IS NOT NULL) AND (tenant_org_id ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'::text) AND ((tenant_org_id)::uuid = ANY (COALESCE(( SELECT current_user_tenant_ids() AS current_user_tenant_ids), ARRAY[]::uuid[])))) OR ( SELECT is_system_admin(uid()) AS is_system_admin) OR (assigned_to = (( SELECT uid() AS uid))::text) OR (lower(assigned_to) = lower(( SELECT current_user_email() AS current_user_email))))","roles":["public"],"tablename":"unified_contacts","permissive":"PERMISSIVE","policyname":"uc_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((assigned_to IS NOT NULL) AND ((assigned_to = (( SELECT uid() AS uid))::text) OR (lower(assigned_to) = lower(( SELECT current_user_email() AS current_user_email)))))","roles":["authenticated"],"tablename":"unified_contacts","permissive":"PERMISSIVE","policyname":"uc_user_assigned_update","schemaname":"public","with_check":"((assigned_to IS NOT NULL) AND ((assigned_to = (( SELECT uid() AS uid))::text) OR (lower(assigned_to) = lower(( SELECT current_user_email() AS current_user_email)))))"}],"triggers":[{"name":"aaa_validate_tenant_org_id","definition":"CREATE TRIGGER aaa_validate_tenant_org_id BEFORE INSERT OR UPDATE OF tenant_org_id ON unified_contacts FOR EACH ROW EXECUTE FUNCTION aaa_validate_tenant_org_id_fn()"},{"name":"audit_trigger_unified_contacts","definition":"CREATE TRIGGER audit_trigger_unified_contacts AFTER INSERT OR DELETE OR UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"},{"name":"automation_dispatch_unified_contacts","definition":"CREATE TRIGGER automation_dispatch_unified_contacts AFTER UPDATE OF status, lead_stage, jobs_stage, claim_stage, assigned_to ON unified_contacts FOR EACH ROW EXECUTE FUNCTION automation_dispatch_on_update()"},{"name":"tr_record_score_change","definition":"CREATE TRIGGER tr_record_score_change AFTER UPDATE OF lead_score ON unified_contacts FOR EACH ROW EXECUTE FUNCTION record_score_change()"},{"name":"trg_apply_configured_lead_source_routing","definition":"CREATE TRIGGER trg_apply_configured_lead_source_routing BEFORE INSERT OR UPDATE OF tenant_org_id, source ON unified_contacts FOR EACH ROW EXECUTE FUNCTION apply_configured_lead_source_routing()"},{"name":"trg_auto_route_new_roof_lead","definition":"CREATE TRIGGER trg_auto_route_new_roof_lead BEFORE INSERT OR UPDATE OF roof_permit_finaled_date, property_year_built, has_recent_roof_permit, deleted_at ON unified_contacts FOR EACH ROW WHEN (new.deleted_at IS NULL) EXECUTE FUNCTION auto_route_new_roof_lead()"},{"name":"trg_dispatch_homeowner_update_on_stage_change","definition":"CREATE TRIGGER trg_dispatch_homeowner_update_on_stage_change AFTER UPDATE OF lead_stage, claim_stage, jobs_stage ON unified_contacts FOR EACH ROW EXECUTE FUNCTION dispatch_homeowner_stage_update()"},{"name":"trg_enforce_assigned_user_tenant_match","definition":"CREATE TRIGGER trg_enforce_assigned_user_tenant_match BEFORE INSERT OR UPDATE OF assigned_user, assigned_to, tenant_org_id ON unified_contacts FOR EACH ROW EXECUTE FUNCTION enforce_assigned_user_tenant_match()"},{"name":"trg_enforce_test_account_rules_iud","definition":"CREATE TRIGGER trg_enforce_test_account_rules_iud BEFORE INSERT OR DELETE OR UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION enforce_test_account_rules()"},{"name":"trg_log_realtor_assignment_change","definition":"CREATE TRIGGER trg_log_realtor_assignment_change AFTER UPDATE OF assigned_user ON unified_contacts FOR EACH ROW EXECUTE FUNCTION log_realtor_assignment_change()"},{"name":"trg_mark_score_stale_on_contact","definition":"CREATE TRIGGER trg_mark_score_stale_on_contact AFTER UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION mark_score_stale_on_contact_change()"},{"name":"trg_notify_owner_appointment","definition":"CREATE TRIGGER trg_notify_owner_appointment AFTER INSERT OR UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION notify_tenant_owner_on_appointment()"},{"name":"trg_revoke_portal_links_on_archive","definition":"CREATE TRIGGER trg_revoke_portal_links_on_archive AFTER UPDATE OF archived_at ON unified_contacts FOR EACH ROW EXECUTE FUNCTION revoke_portal_links_on_archive()"},{"name":"trg_scrub_unified_contacts_dnc","definition":"CREATE TRIGGER trg_scrub_unified_contacts_dnc BEFORE INSERT OR UPDATE OF phone ON unified_contacts FOR EACH ROW EXECUTE FUNCTION scrub_lead_against_dnc()"},{"name":"trg_sync_linked_contacts","definition":"CREATE TRIGGER trg_sync_linked_contacts AFTER UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION sync_linked_contacts()"},{"name":"trg_unified_contacts_autofill_name","definition":"CREATE TRIGGER trg_unified_contacts_autofill_name BEFORE INSERT OR UPDATE OF first_name, last_name, name ON unified_contacts FOR EACH ROW EXECUTE FUNCTION unified_contacts_autofill_name()"},{"name":"trg_unified_contacts_mark_scores_stale","definition":"CREATE TRIGGER trg_unified_contacts_mark_scores_stale AFTER UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION mark_scores_stale_for_contact()"},{"name":"trg_validate_assigned_to_uc","definition":"CREATE TRIGGER trg_validate_assigned_to_uc BEFORE INSERT OR UPDATE OF assigned_to ON unified_contacts FOR EACH ROW EXECUTE FUNCTION validate_assigned_to_uuid()"},{"name":"unified_contacts_auto_graduate","definition":"CREATE TRIGGER unified_contacts_auto_graduate BEFORE UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION auto_graduate_lead()"},{"name":"unified_contacts_mirror_assigned","definition":"CREATE TRIGGER unified_contacts_mirror_assigned BEFORE INSERT OR UPDATE OF assigned_to, assigned_user ON unified_contacts FOR EACH ROW EXECUTE FUNCTION tg_unified_contacts_mirror_assigned()"},{"name":"unified_contacts_quality_score","definition":"CREATE TRIGGER unified_contacts_quality_score BEFORE INSERT OR UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION update_quality_score()"},{"name":"unified_contacts_updated_at","definition":"CREATE TRIGGER unified_contacts_updated_at BEFORE UPDATE ON unified_contacts FOR EACH ROW EXECUTE FUNCTION update_unified_contacts_updated_at()"}],"constraints":[{"name":"unified_contacts_contact_id_key","definition":"UNIQUE (contact_id)"},{"name":"unified_contacts_lead_origin_check","definition":"CHECK (lead_origin = ANY (ARRAY['system'::text, 'personal'::text]))"},{"name":"unified_contacts_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"unified_contacts_insert_violations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"occurred_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"violation_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"attempted_tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempted_lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"auth_uid","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"application_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"client_addr","type":"inet","default":null,"identity":"","not_null":false,"generated":""},{"name":"raw_row","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_uc_insert_violations_occurred_at","definition":"CREATE INDEX idx_uc_insert_violations_occurred_at ON public.unified_contacts_insert_violations USING btree (occurred_at DESC)"},{"name":"idx_uc_insert_violations_type","definition":"CREATE INDEX idx_uc_insert_violations_type ON public.unified_contacts_insert_violations USING btree (violation_type)"},{"name":"unified_contacts_insert_violations_pkey","definition":"CREATE UNIQUE INDEX unified_contacts_insert_violations_pkey ON public.unified_contacts_insert_violations USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"unified_contacts_insert_violations","permissive":"PERMISSIVE","policyname":"system_admins_read_uc_insert_violations","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"unified_contacts_insert_violations_pkey","definition":"PRIMARY KEY (id)"},{"name":"unified_contacts_insert_violations_violation_type_check","definition":"CHECK (violation_type = ANY (ARRAY['null_tenant'::text, 'orphan_tenant'::text]))"}]},{"table":"unified_inbox","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"channel","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"direction","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"subject","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"body","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"preview","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"from_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"thread_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_read","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_starred","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"is_archived","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"labels","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"received_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_unified_inbox_channel","definition":"CREATE INDEX idx_unified_inbox_channel ON public.unified_inbox USING btree (channel)"},{"name":"idx_unified_inbox_contact","definition":"CREATE INDEX idx_unified_inbox_contact ON public.unified_inbox USING btree (contact_id)"},{"name":"idx_unified_inbox_tenant","definition":"CREATE INDEX idx_unified_inbox_tenant ON public.unified_inbox USING btree (tenant_id)"},{"name":"idx_unified_inbox_unread","definition":"CREATE INDEX idx_unified_inbox_unread ON public.unified_inbox USING btree (tenant_id, is_read, is_archived)"},{"name":"unified_inbox_pkey","definition":"CREATE UNIQUE INDEX unified_inbox_pkey ON public.unified_inbox USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(tenant_id IN ( SELECT user_roles.tenant_id\n   FROM user_roles\n  WHERE (user_roles.user_id = uid())))","roles":["public"],"tablename":"unified_inbox","permissive":"PERMISSIVE","policyname":"Tenant isolation for unified_inbox","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"unified_inbox_channel_check","definition":"CHECK (channel = ANY (ARRAY['email'::text, 'sms'::text, 'call'::text, 'voicemail'::text, 'chat'::text, 'social'::text]))"},{"name":"unified_inbox_contact_id_fkey","definition":"FOREIGN KEY (contact_id) REFERENCES unified_contacts(id) ON DELETE SET NULL"},{"name":"unified_inbox_direction_check","definition":"CHECK (direction = ANY (ARRAY['inbound'::text, 'outbound'::text]))"},{"name":"unified_inbox_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"usage_counters","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"feature_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_start","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"count","type":"bigint","default":"0","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_usage_counters_tenant_period","definition":"CREATE INDEX idx_usage_counters_tenant_period ON public.usage_counters USING btree (tenant_id, period_start DESC)"},{"name":"usage_counters_pkey","definition":"CREATE UNIQUE INDEX usage_counters_pkey ON public.usage_counters USING btree (id)"},{"name":"usage_counters_tenant_id_feature_key_period_start_key","definition":"CREATE UNIQUE INDEX usage_counters_tenant_id_feature_key_period_start_key ON public.usage_counters USING btree (tenant_id, feature_key, period_start)"}],"policies":[{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"usage_counters","permissive":"PERMISSIVE","policyname":"Only system admins write usage counters","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = usage_counters.tenant_id) AND (m.status = 'active'::text)))))","roles":["public"],"tablename":"usage_counters","permissive":"PERMISSIVE","policyname":"Tenant members read usage counters","schemaname":"public","with_check":null}],"triggers":[{"name":"update_usage_counters_updated_at","definition":"CREATE TRIGGER update_usage_counters_updated_at BEFORE UPDATE ON usage_counters FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"usage_counters_pkey","definition":"PRIMARY KEY (id)"},{"name":"usage_counters_tenant_id_feature_key_period_start_key","definition":"UNIQUE (tenant_id, feature_key, period_start)"}]},{"table":"user_achievements","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"achievement_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"earned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"progress","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"notified","type":"boolean","default":"false","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_user_achievements_tenant","definition":"CREATE INDEX idx_user_achievements_tenant ON public.user_achievements USING btree (tenant_org_id)"},{"name":"idx_user_achievements_user_id","definition":"CREATE INDEX idx_user_achievements_user_id ON public.user_achievements USING btree (user_id)"},{"name":"user_achievements_pkey","definition":"CREATE UNIQUE INDEX user_achievements_pkey ON public.user_achievements USING btree (id)"},{"name":"user_achievements_user_id_achievement_id_key","definition":"CREATE UNIQUE INDEX user_achievements_user_id_achievement_id_key ON public.user_achievements USING btree (user_id, achievement_id)"}],"policies":[{"cmd":"SELECT","qual":"(uid() = user_id)","roles":["public"],"tablename":"user_achievements","permissive":"PERMISSIVE","policyname":"Users view own achievements","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"user_achievements_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_achievements_user_id_achievement_id_key","definition":"UNIQUE (user_id, achievement_id)"}]},{"table":"user_calendar_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_to","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"claim_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_type","type":"text","default":"'appointment'::text","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'scheduled'::text","identity":"","not_null":true,"generated":""},{"name":"pipeline","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"pipeline_stage","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"start_time","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"end_time","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"location","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"reminder_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_auto_generated","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"all_day","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"recurrence_rule","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"series_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"event_booking_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_uce_assigned","definition":"CREATE INDEX idx_uce_assigned ON public.user_calendar_events USING btree (assigned_to)"},{"name":"idx_uce_contact","definition":"CREATE INDEX idx_uce_contact ON public.user_calendar_events USING btree (contact_id)"},{"name":"idx_uce_start","definition":"CREATE INDEX idx_uce_start ON public.user_calendar_events USING btree (start_time)"},{"name":"idx_uce_status","definition":"CREATE INDEX idx_uce_status ON public.user_calendar_events USING btree (status)"},{"name":"idx_uce_tenant","definition":"CREATE INDEX idx_uce_tenant ON public.user_calendar_events USING btree (tenant_org_id)"},{"name":"idx_uce_user","definition":"CREATE INDEX idx_uce_user ON public.user_calendar_events USING btree (user_id)"},{"name":"user_calendar_events_event_booking_idx","definition":"CREATE INDEX user_calendar_events_event_booking_idx ON public.user_calendar_events USING btree (event_booking_id)"},{"name":"user_calendar_events_pkey","definition":"CREATE UNIQUE INDEX user_calendar_events_pkey ON public.user_calendar_events USING btree (id)"},{"name":"user_calendar_events_series_idx","definition":"CREATE INDEX user_calendar_events_series_idx ON public.user_calendar_events USING btree (tenant_org_id, series_id) WHERE (series_id IS NOT NULL)"},{"name":"user_calendar_events_tenant_start_idx","definition":"CREATE INDEX user_calendar_events_tenant_start_idx ON public.user_calendar_events USING btree (tenant_org_id, start_time)"}],"policies":[{"cmd":"DELETE","qual":"((uid() = user_id) OR uce_is_owner_or_admin(tenant_org_id))","roles":["public"],"tablename":"user_calendar_events","permissive":"PERMISSIVE","policyname":"uce_delete_owner_or_admin","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"user_calendar_events","permissive":"PERMISSIVE","policyname":"uce_insert_tenant_member","schemaname":"public","with_check":"((uid() = user_id) AND uce_is_member(tenant_org_id))"},{"cmd":"SELECT","qual":"((uid() = user_id) OR (assigned_to = ( SELECT profiles.email\n   FROM profiles\n  WHERE (profiles.id = uid()))) OR uce_is_owner_or_admin(tenant_org_id))","roles":["public"],"tablename":"user_calendar_events","permissive":"PERMISSIVE","policyname":"uce_select_own_or_assigned","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((uid() = user_id) OR (assigned_to = ( SELECT profiles.email\n   FROM profiles\n  WHERE (profiles.id = uid()))) OR uce_is_owner_or_admin(tenant_org_id))","roles":["public"],"tablename":"user_calendar_events","permissive":"PERMISSIVE","policyname":"uce_update_owner_or_assigned_or_admin","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_enforce_calendar_claim_context","definition":"CREATE TRIGGER trg_enforce_calendar_claim_context BEFORE INSERT OR UPDATE OF claim_id, contact_id, tenant_org_id ON user_calendar_events FOR EACH ROW EXECUTE FUNCTION enforce_calendar_claim_context()"},{"name":"trg_uce_updated_at","definition":"CREATE TRIGGER trg_uce_updated_at BEFORE UPDATE ON user_calendar_events FOR EACH ROW EXECUTE FUNCTION tg_uce_updated_at()"}],"constraints":[{"name":"user_calendar_events_event_booking_id_fkey","definition":"FOREIGN KEY (event_booking_id) REFERENCES event_bookings(id) ON DELETE SET NULL"},{"name":"user_calendar_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"user_changelog_reads","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"changelog_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"read_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_user_changelog_reads_user","definition":"CREATE INDEX idx_user_changelog_reads_user ON public.user_changelog_reads USING btree (user_id)"},{"name":"user_changelog_reads_pkey","definition":"CREATE UNIQUE INDEX user_changelog_reads_pkey ON public.user_changelog_reads USING btree (id)"},{"name":"user_changelog_reads_user_id_changelog_id_key","definition":"CREATE UNIQUE INDEX user_changelog_reads_user_id_changelog_id_key ON public.user_changelog_reads USING btree (user_id, changelog_id)"}],"policies":[{"cmd":"DELETE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"user_changelog_reads","permissive":"PERMISSIVE","policyname":"Users delete their own changelog reads","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_changelog_reads","permissive":"PERMISSIVE","policyname":"Users insert their own changelog reads","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"user_changelog_reads","permissive":"PERMISSIVE","policyname":"Users view their own changelog reads","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"user_changelog_reads_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_changelog_reads_user_id_changelog_id_key","definition":"UNIQUE (user_id, changelog_id)"}]},{"table":"user_extensions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"extension","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"ring_strategy","type":"text","default":"'device_then_phone'::text","identity":"","not_null":true,"generated":""},{"name":"voicemail_fallback","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"display_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_user_extensions_tenant","definition":"CREATE INDEX idx_user_extensions_tenant ON public.user_extensions USING btree (tenant_org_id)"},{"name":"idx_user_extensions_user","definition":"CREATE INDEX idx_user_extensions_user ON public.user_extensions USING btree (user_id)"},{"name":"user_extensions_pkey","definition":"CREATE UNIQUE INDEX user_extensions_pkey ON public.user_extensions USING btree (id)"},{"name":"user_extensions_tenant_org_id_extension_key","definition":"CREATE UNIQUE INDEX user_extensions_tenant_org_id_extension_key ON public.user_extensions USING btree (tenant_org_id, extension)"},{"name":"user_extensions_tenant_org_id_user_id_key","definition":"CREATE UNIQUE INDEX user_extensions_tenant_org_id_user_id_key ON public.user_extensions USING btree (tenant_org_id, user_id)"}],"policies":[{"cmd":"DELETE","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"user_extensions","permissive":"PERMISSIVE","policyname":"Managers+ can delete extensions","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_extensions","permissive":"PERMISSIVE","policyname":"Managers+ can insert extensions","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"},{"cmd":"UPDATE","qual":"is_manager_or_higher(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"user_extensions","permissive":"PERMISSIVE","policyname":"Managers+ can update extensions","schemaname":"public","with_check":"is_manager_or_higher(uid(), tenant_org_id)"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"user_extensions","permissive":"PERMISSIVE","policyname":"Tenant members can view extensions","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_user_extensions_updated","definition":"CREATE TRIGGER trg_user_extensions_updated BEFORE UPDATE ON user_extensions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"user_extensions_extension_check","definition":"CHECK (extension ~ '^[0-9]{3,5}$'::text)"},{"name":"user_extensions_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_extensions_ring_strategy_check","definition":"CHECK (ring_strategy = ANY (ARRAY['device_only'::text, 'phone_only'::text, 'device_then_phone'::text, 'simultaneous'::text]))"},{"name":"user_extensions_tenant_org_id_extension_key","definition":"UNIQUE (tenant_org_id, extension)"},{"name":"user_extensions_tenant_org_id_user_id_key","definition":"UNIQUE (tenant_org_id, user_id)"}]},{"table":"user_feature_overrides","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"feature_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"user_feature_override_status","default":"'inherit'::user_feature_override_status","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'manual_override'::text","identity":"","not_null":true,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_ufo_feature","definition":"CREATE INDEX idx_ufo_feature ON public.user_feature_overrides USING btree (feature_key)"},{"name":"idx_ufo_tenant_user","definition":"CREATE INDEX idx_ufo_tenant_user ON public.user_feature_overrides USING btree (tenant_org_id, user_id)"},{"name":"user_feature_overrides_pkey","definition":"CREATE UNIQUE INDEX user_feature_overrides_pkey ON public.user_feature_overrides USING btree (id)"},{"name":"user_feature_overrides_tenant_org_id_user_id_feature_key_key","definition":"CREATE UNIQUE INDEX user_feature_overrides_tenant_org_id_user_id_feature_key_key ON public.user_feature_overrides USING btree (tenant_org_id, user_id, feature_key)"}],"policies":[{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"user_feature_overrides","permissive":"PERMISSIVE","policyname":"ufo self read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"user_feature_overrides","permissive":"PERMISSIVE","policyname":"ufo system admin all","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"ufo_set_updated_at","definition":"CREATE TRIGGER ufo_set_updated_at BEFORE UPDATE ON user_feature_overrides FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"user_feature_overrides_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_feature_overrides_tenant_org_id_user_id_feature_key_key","definition":"UNIQUE (tenant_org_id, user_id, feature_key)"}]},{"table":"user_invitations","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"text","default":"'user'::text","identity":"","not_null":false,"generated":""},{"name":"invited_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"invited_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"accepted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":"(now() + '7 days'::interval)","identity":"","not_null":false,"generated":""},{"name":"invitation_token","type":"text","default":"encode(gen_random_bytes(32), 'hex'::text)","identity":"","not_null":false,"generated":""},{"name":"email_opens_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_opened_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_user_invitations_email","definition":"CREATE INDEX idx_user_invitations_email ON public.user_invitations USING btree (email)"},{"name":"idx_user_invitations_phone","definition":"CREATE INDEX idx_user_invitations_phone ON public.user_invitations USING btree (phone) WHERE (phone IS NOT NULL)"},{"name":"idx_user_invitations_status","definition":"CREATE INDEX idx_user_invitations_status ON public.user_invitations USING btree (status)"},{"name":"idx_user_invitations_tenant_id","definition":"CREATE INDEX idx_user_invitations_tenant_id ON public.user_invitations USING btree (tenant_id)"},{"name":"idx_user_invitations_token","definition":"CREATE INDEX idx_user_invitations_token ON public.user_invitations USING btree (invitation_token)"},{"name":"user_invitations_invitation_token_key","definition":"CREATE UNIQUE INDEX user_invitations_invitation_token_key ON public.user_invitations USING btree (invitation_token)"},{"name":"user_invitations_pkey","definition":"CREATE UNIQUE INDEX user_invitations_pkey ON public.user_invitations USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_invitations","permissive":"PERMISSIVE","policyname":"invitation_managers_insert","schemaname":"public","with_check":"((status = 'pending'::text) AND ((is_system_admin(uid()) AND (role = ANY (ARRAY['Tenant Owner'::text, 'Manager'::text, 'Office Staff'::text, 'Rep'::text, 'Crew'::text, 'PM'::text, 'PA'::text, 'Roofer'::text, 'Broker'::text, 'Agent'::text, 'Listing Agent'::text, 'Buyer Agent'::text, 'ISA'::text, 'Showing Agent'::text, 'TC'::text]))) OR ((EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships utm ON (((utm.user_id = ur.user_id) AND (utm.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = user_invitations.tenant_id) AND (utm.status = 'active'::text) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text, 'GodMode'::text, 'Manager'::text]))))) AND (role = ANY (ARRAY['Manager'::text, 'Office Staff'::text, 'Rep'::text, 'Crew'::text, 'PM'::text, 'PA'::text, 'Roofer'::text, 'Broker'::text, 'Agent'::text, 'Listing Agent'::text, 'Buyer Agent'::text, 'ISA'::text, 'Showing Agent'::text, 'TC'::text])))))"},{"cmd":"SELECT","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships utm ON (((utm.user_id = ur.user_id) AND (utm.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = user_invitations.tenant_id) AND (utm.status = 'active'::text) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text, 'GodMode'::text, 'Manager'::text]))))))","roles":["authenticated"],"tablename":"user_invitations","permissive":"PERMISSIVE","policyname":"invitation_managers_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships utm ON (((utm.user_id = ur.user_id) AND (utm.tenant_id = ur.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = user_invitations.tenant_id) AND (utm.status = 'active'::text) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text, 'GodMode'::text, 'Manager'::text]))))))","roles":["authenticated"],"tablename":"user_invitations","permissive":"PERMISSIVE","policyname":"invitation_managers_update","schemaname":"public","with_check":"((status = ANY (ARRAY['pending'::text, 'expired'::text, 'cancelled'::text])) AND ((is_system_admin(uid()) AND (role = ANY (ARRAY['Tenant Owner'::text, 'Manager'::text, 'Office Staff'::text, 'Rep'::text, 'Crew'::text, 'PM'::text, 'PA'::text, 'Roofer'::text, 'Broker'::text, 'Agent'::text, 'Listing Agent'::text, 'Buyer Agent'::text, 'ISA'::text, 'Showing Agent'::text, 'TC'::text]))) OR ((EXISTS ( SELECT 1\n   FROM (user_roles ur\n     JOIN security_active_user_tenant_memberships utm ON (((utm.user_id = ur.user_id) AND (utm.tenant_id = user_invitations.tenant_id))))\n  WHERE ((ur.user_id = uid()) AND (ur.tenant_id = user_invitations.tenant_id) AND (utm.status = 'active'::text) AND ((ur.role)::text = ANY (ARRAY['Owner'::text, 'Tenant Owner'::text, 'Admin'::text, 'GodMode'::text, 'Manager'::text]))))) AND (role = ANY (ARRAY['Manager'::text, 'Office Staff'::text, 'Rep'::text, 'Crew'::text, 'PM'::text, 'PA'::text, 'Roofer'::text, 'Broker'::text, 'Agent'::text, 'Listing Agent'::text, 'Buyer Agent'::text, 'ISA'::text, 'Showing Agent'::text, 'TC'::text])))))"}],"triggers":[{"name":"protect_accepted_user_invitations","definition":"CREATE TRIGGER protect_accepted_user_invitations BEFORE UPDATE ON user_invitations FOR EACH ROW EXECUTE FUNCTION prevent_accepted_invitation_mutation()"},{"name":"update_user_invitations_updated_at","definition":"CREATE TRIGGER update_user_invitations_updated_at BEFORE UPDATE ON user_invitations FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"user_invitations_identity_required","definition":"CHECK (NULLIF(btrim(email), ''::text) IS NOT NULL OR NULLIF(btrim(phone), ''::text) IS NOT NULL)"},{"name":"user_invitations_invitation_token_key","definition":"UNIQUE (invitation_token)"},{"name":"user_invitations_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_invitations_status_check","definition":"CHECK (status = ANY (ARRAY['pending'::text, 'sent'::text, 'opened'::text, 'accepted'::text, 'expired'::text, 'cancelled'::text]))"}]},{"table":"user_lead_pointer","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"current_lead_index","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_user_lead_pointer_user_tenant","definition":"CREATE INDEX idx_user_lead_pointer_user_tenant ON public.user_lead_pointer USING btree (user_id, tenant_id)"},{"name":"user_lead_pointer_pkey","definition":"CREATE UNIQUE INDEX user_lead_pointer_pkey ON public.user_lead_pointer USING btree (id)"},{"name":"user_lead_pointer_user_id_tenant_id_key","definition":"CREATE UNIQUE INDEX user_lead_pointer_user_id_tenant_id_key ON public.user_lead_pointer USING btree (user_id, tenant_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_lead_pointer","permissive":"PERMISSIVE","policyname":"Users can insert own pointer","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"user_lead_pointer","permissive":"PERMISSIVE","policyname":"Users can update own pointer","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"SELECT","qual":"(user_id = uid())","roles":["authenticated"],"tablename":"user_lead_pointer","permissive":"PERMISSIVE","policyname":"Users can view own pointer","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"user_lead_pointer_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_lead_pointer_user_id_tenant_id_key","definition":"UNIQUE (user_id, tenant_id)"}]},{"table":"user_permission_overrides","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"permission_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"granted","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"reason","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"user_permission_overrides_pkey","definition":"CREATE UNIQUE INDEX user_permission_overrides_pkey ON public.user_permission_overrides USING btree (id)"},{"name":"user_permission_overrides_user_id_permission_key_tenant_id_key","definition":"CREATE UNIQUE INDEX user_permission_overrides_user_id_permission_key_tenant_id_key ON public.user_permission_overrides USING btree (user_id, permission_key, tenant_id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"user_permission_overrides","permissive":"PERMISSIVE","policyname":"platform_admin_view_permission_overrides","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"user_permission_overrides_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_permission_overrides_user_id_permission_key_tenant_id_key","definition":"UNIQUE (user_id, permission_key, tenant_id)"}]},{"table":"user_roles","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"role","type":"app_role","default":null,"identity":"","not_null":true,"generated":""},{"name":"assigned_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"bypass_tcpa_hours","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_user_roles_tenant","definition":"CREATE INDEX idx_user_roles_tenant ON public.user_roles USING btree (tenant_id)"},{"name":"user_roles_one_platform_godmode_per_user","definition":"CREATE UNIQUE INDEX user_roles_one_platform_godmode_per_user ON public.user_roles USING btree (user_id) WHERE ((tenant_id IS NULL) AND (role = 'GodMode'::app_role))"},{"name":"user_roles_pkey","definition":"CREATE UNIQUE INDEX user_roles_pkey ON public.user_roles USING btree (id)"},{"name":"user_roles_user_id_tenant_id_role_key","definition":"CREATE UNIQUE INDEX user_roles_user_id_tenant_id_role_key ON public.user_roles USING btree (user_id, tenant_id, role)"},{"name":"user_roles_user_tenant_unique","definition":"CREATE UNIQUE INDEX user_roles_user_tenant_unique ON public.user_roles USING btree (user_id, tenant_id)"}],"policies":[{"cmd":"DELETE","qual":"((user_id = ( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin) OR is_admin_or_higher(( SELECT uid() AS uid), tenant_id))","roles":["public"],"tablename":"user_roles","permissive":"PERMISSIVE","policyname":"Admins can delete roles","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"user_roles","permissive":"PERMISSIVE","policyname":"Admins can insert roles","schemaname":"public","with_check":"(( SELECT is_system_admin(uid()) AS is_system_admin) OR is_admin_or_higher(( SELECT uid() AS uid), tenant_id))"},{"cmd":"UPDATE","qual":"((user_id = ( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin) OR is_admin_or_higher(( SELECT uid() AS uid), tenant_id))","roles":["public"],"tablename":"user_roles","permissive":"PERMISSIVE","policyname":"Admins can update roles","schemaname":"public","with_check":"(( SELECT is_system_admin(uid()) AS is_system_admin) OR is_admin_or_higher(( SELECT uid() AS uid), tenant_id))"},{"cmd":"SELECT","qual":"((user_id = ( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin) OR is_admin_or_higher(( SELECT uid() AS uid), tenant_id) OR is_manager_pm_or_higher(( SELECT uid() AS uid), tenant_id) OR is_tenant_owner_membership(( SELECT uid() AS uid), tenant_id) OR is_tenant_owner_for(( SELECT uid() AS uid), (tenant_id)::text))","roles":["public"],"tablename":"user_roles","permissive":"PERMISSIVE","policyname":"Visible tenant user roles","schemaname":"public","with_check":null}],"triggers":[{"name":"audit_trigger_user_roles","definition":"CREATE TRIGGER audit_trigger_user_roles AFTER INSERT OR DELETE OR UPDATE ON user_roles FOR EACH ROW EXECUTE FUNCTION comprehensive_audit_trigger_fn()"},{"name":"trg_reconcile_default_role_insert","definition":"CREATE TRIGGER trg_reconcile_default_role_insert BEFORE INSERT ON user_roles FOR EACH ROW EXECUTE FUNCTION reconcile_default_role_insert()"},{"name":"trg_sync_profile_role_del","definition":"CREATE TRIGGER trg_sync_profile_role_del AFTER DELETE ON user_roles FOR EACH ROW EXECUTE FUNCTION sync_profile_role_from_user_roles()"},{"name":"trg_sync_profile_role_ins","definition":"CREATE TRIGGER trg_sync_profile_role_ins AFTER INSERT ON user_roles FOR EACH ROW EXECUTE FUNCTION sync_profile_role_from_user_roles()"},{"name":"trg_sync_profile_role_upd","definition":"CREATE TRIGGER trg_sync_profile_role_upd AFTER UPDATE ON user_roles FOR EACH ROW EXECUTE FUNCTION sync_profile_role_from_user_roles()"},{"name":"trg_sync_role_to_membership","definition":"CREATE TRIGGER trg_sync_role_to_membership AFTER INSERT ON user_roles FOR EACH ROW EXECUTE FUNCTION sync_role_to_membership()"},{"name":"zz_security_validate_role_scope_update","definition":"CREATE TRIGGER zz_security_validate_role_scope_update BEFORE INSERT OR UPDATE OF user_id, tenant_id ON user_roles FOR EACH ROW EXECUTE FUNCTION security_validate_role_scope_update()"}],"constraints":[{"name":"user_roles_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_roles_platform_role_only","definition":"CHECK (tenant_id IS NOT NULL OR role = 'GodMode'::app_role)"},{"name":"user_roles_user_id_tenant_id_role_key","definition":"UNIQUE (user_id, tenant_id, role)"},{"name":"user_roles_user_tenant_unique","definition":"UNIQUE (user_id, tenant_id)"}]},{"table":"user_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"session_token_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_agent","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"device_info","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"location_info","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"last_activity_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"ended_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"end_reason","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"current_page","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_page_title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_user_sessions_active","definition":"CREATE INDEX idx_user_sessions_active ON public.user_sessions USING btree (is_active, last_activity_at)"},{"name":"idx_user_sessions_user","definition":"CREATE INDEX idx_user_sessions_user ON public.user_sessions USING btree (user_id, is_active)"},{"name":"idx_user_sessions_user_active","definition":"CREATE INDEX idx_user_sessions_user_active ON public.user_sessions USING btree (user_id, is_active) WHERE (is_active = true)"},{"name":"user_sessions_pkey","definition":"CREATE UNIQUE INDEX user_sessions_pkey ON public.user_sessions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((user_id = uid()) OR is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships target_membership\n     JOIN user_roles admin_role ON (((admin_role.tenant_id = target_membership.tenant_id) AND (admin_role.user_id = uid()) AND ((admin_role.role)::text = ANY (ARRAY['Admin'::text, 'Owner'::text, 'Tenant Owner'::text])))))\n  WHERE ((target_membership.user_id = user_sessions.user_id) AND (target_membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"user_sessions","permissive":"PERMISSIVE","policyname":"Tenant admins can view scoped sessions","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((uid() = user_id) OR is_system_admin(uid()))","roles":["authenticated"],"tablename":"user_sessions","permissive":"PERMISSIVE","policyname":"Users and admins can view sessions","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_sessions","permissive":"PERMISSIVE","policyname":"Users can insert own sessions","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"UPDATE","qual":"(uid() = user_id)","roles":["authenticated"],"tablename":"user_sessions","permissive":"PERMISSIVE","policyname":"Users can update own sessions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"user_sessions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"user_tenant_memberships","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"invited_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"joined_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"last_accessed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"is_owner","type":"boolean","default":"false","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_memberships_status","definition":"CREATE INDEX idx_memberships_status ON public.user_tenant_memberships USING btree (status)"},{"name":"idx_memberships_tenant","definition":"CREATE INDEX idx_memberships_tenant ON public.user_tenant_memberships USING btree (tenant_id)"},{"name":"idx_memberships_user","definition":"CREATE INDEX idx_memberships_user ON public.user_tenant_memberships USING btree (user_id)"},{"name":"idx_user_tenant_memberships_user_tenant","definition":"CREATE INDEX idx_user_tenant_memberships_user_tenant ON public.user_tenant_memberships USING btree (user_id, tenant_id, status)"},{"name":"user_tenant_memberships_pkey","definition":"CREATE UNIQUE INDEX user_tenant_memberships_pkey ON public.user_tenant_memberships USING btree (id)"},{"name":"user_tenant_memberships_user_id_tenant_id_key","definition":"CREATE UNIQUE INDEX user_tenant_memberships_user_id_tenant_id_key ON public.user_tenant_memberships USING btree (user_id, tenant_id)"}],"policies":[{"cmd":"DELETE","qual":"is_admin_or_higher(( SELECT uid() AS uid), tenant_id)","roles":["public"],"tablename":"user_tenant_memberships","permissive":"PERMISSIVE","policyname":"Admins can delete memberships","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"user_tenant_memberships","permissive":"PERMISSIVE","policyname":"Admins can insert memberships","schemaname":"public","with_check":"is_admin_or_higher(( SELECT uid() AS uid), tenant_id)"},{"cmd":"UPDATE","qual":"is_admin_or_higher(( SELECT uid() AS uid), tenant_id)","roles":["public"],"tablename":"user_tenant_memberships","permissive":"PERMISSIVE","policyname":"Admins can update memberships","schemaname":"public","with_check":"is_admin_or_higher(( SELECT uid() AS uid), tenant_id)"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_tenant_memberships","permissive":"PERMISSIVE","policyname":"Users can request to join tenants","schemaname":"public","with_check":"((user_id = uid()) AND (status = 'pending'::text) AND (COALESCE(is_owner, false) = false) AND (invited_by IS NULL))"},{"cmd":"SELECT","qual":"((user_id = ( SELECT uid() AS uid)) OR ( SELECT is_system_admin(uid()) AS is_system_admin) OR is_admin_or_higher(( SELECT uid() AS uid), tenant_id) OR is_manager_pm_or_higher(( SELECT uid() AS uid), tenant_id))","roles":["public"],"tablename":"user_tenant_memberships","permissive":"PERMISSIVE","policyname":"Visible tenant memberships","schemaname":"public","with_check":null}],"triggers":[{"name":"throttle_membership_access_touch","definition":"CREATE TRIGGER throttle_membership_access_touch BEFORE UPDATE OF last_accessed_at ON user_tenant_memberships FOR EACH ROW EXECUTE FUNCTION throttle_membership_access_touch()"},{"name":"trg_auto_enroll_onboarding","definition":"CREATE TRIGGER trg_auto_enroll_onboarding AFTER INSERT OR UPDATE OF status, tenant_id ON user_tenant_memberships FOR EACH ROW EXECUTE FUNCTION auto_enroll_academy_onboarding()"},{"name":"trg_reconcile_configured_lead_source_routing_on_membership","definition":"CREATE TRIGGER trg_reconcile_configured_lead_source_routing_on_membership AFTER INSERT OR UPDATE OF status ON user_tenant_memberships FOR EACH ROW EXECUTE FUNCTION reconcile_configured_lead_source_routing_on_membership()"},{"name":"trg_sync_membership_to_role","definition":"CREATE TRIGGER trg_sync_membership_to_role AFTER INSERT OR UPDATE OF status, is_owner ON user_tenant_memberships FOR EACH ROW EXECUTE FUNCTION sync_membership_to_role()"},{"name":"zz_security_remove_roles_for_inactive_membership","definition":"CREATE TRIGGER zz_security_remove_roles_for_inactive_membership AFTER DELETE OR UPDATE OF status ON user_tenant_memberships FOR EACH ROW EXECUTE FUNCTION security_remove_roles_for_inactive_membership()"}],"constraints":[{"name":"user_tenant_memberships_pkey","definition":"PRIMARY KEY (id)"},{"name":"user_tenant_memberships_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'pending'::text, 'suspended'::text]))"},{"name":"user_tenant_memberships_user_id_tenant_id_key","definition":"UNIQUE (user_id, tenant_id)"}]},{"table":"user_tenant_tutorial_progress","schema":"public","columns":[{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tutorial_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tutorial_version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"prompted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completion_kind","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"user_tenant_tutorial_progress_lookup_idx","definition":"CREATE INDEX user_tenant_tutorial_progress_lookup_idx ON public.user_tenant_tutorial_progress USING btree (tenant_id, user_id, tutorial_key)"},{"name":"user_tenant_tutorial_progress_pkey","definition":"CREATE UNIQUE INDEX user_tenant_tutorial_progress_pkey ON public.user_tenant_tutorial_progress USING btree (user_id, tenant_id, tutorial_key, tutorial_version)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_tenant_tutorial_progress","permissive":"PERMISSIVE","policyname":"Users can create their tenant tutorial progress","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_progress.tenant_id) AND (membership.status = 'active'::text)))))"},{"cmd":"SELECT","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_progress.tenant_id) AND (membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"user_tenant_tutorial_progress","permissive":"PERMISSIVE","policyname":"Users can read their tenant tutorial progress","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_progress.tenant_id) AND (membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"user_tenant_tutorial_progress","permissive":"PERMISSIVE","policyname":"Users can update their tenant tutorial progress","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_progress.tenant_id) AND (membership.status = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"user_tenant_tutorial_progress_completion_kind_check","definition":"CHECK (completion_kind IS NULL OR (completion_kind = ANY (ARRAY['done'::text, 'skipped'::text])))"},{"name":"user_tenant_tutorial_progress_pkey","definition":"PRIMARY KEY (user_id, tenant_id, tutorial_key, tutorial_version)"},{"name":"user_tenant_tutorial_progress_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"user_tenant_tutorial_progress_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"user_tenant_tutorial_state","schema":"public","columns":[{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"completion_kind","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tour_version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"user_tenant_tutorial_state_pkey","definition":"CREATE UNIQUE INDEX user_tenant_tutorial_state_pkey ON public.user_tenant_tutorial_state USING btree (user_id, tenant_id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"user_tenant_tutorial_state","permissive":"PERMISSIVE","policyname":"Users can create their tenant tutorial state","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_state.tenant_id) AND (membership.status = 'active'::text)))))"},{"cmd":"SELECT","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_state.tenant_id) AND (membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"user_tenant_tutorial_state","permissive":"PERMISSIVE","policyname":"Users can read their tenant tutorial state","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_state.tenant_id) AND (membership.status = 'active'::text)))))","roles":["authenticated"],"tablename":"user_tenant_tutorial_state","permissive":"PERMISSIVE","policyname":"Users can update their tenant tutorial state","schemaname":"public","with_check":"((uid() = user_id) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = user_tenant_tutorial_state.tenant_id) AND (membership.status = 'active'::text)))))"}],"triggers":[],"constraints":[{"name":"user_tenant_tutorial_state_completion_kind_check","definition":"CHECK (completion_kind = ANY (ARRAY['done'::text, 'skipped'::text]))"},{"name":"user_tenant_tutorial_state_pkey","definition":"PRIMARY KEY (user_id, tenant_id)"},{"name":"user_tenant_tutorial_state_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"},{"name":"user_tenant_tutorial_state_user_id_fkey","definition":"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"}]},{"table":"vehicle_lockout_requests","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"customer_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"phone","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_location","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"city","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"vehicle_year","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"vehicle_make","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"vehicle_model","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"vehicle_color","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"license_plate","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"keys_location","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'requested'::text","identity":"","not_null":true,"generated":""},{"name":"ownership_confirmed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"authorization_consented","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"authorization_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authorization_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"proof_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"proof_filename","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"technician_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"amount_due","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"amount_paid","type":"numeric(12,2)","default":null,"identity":"","not_null":false,"generated":""},{"name":"payment_status","type":"text","default":"'unpaid'::text","identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":"'public_site'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"en_route_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"on_scene_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"canceled_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_evidence_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"service_evidence_filename","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authority_verified","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"authority_verification_method","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authority_verified_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"completion_acknowledged","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"completion_acknowledgement_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"completion_acknowledged_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"identity_document_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"identity_proof_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"identity_proof_filename","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"identity_deferred","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"authority_basis","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authority_document_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authority_proof_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authority_proof_filename","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"terms_version","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"authorization_agreement_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"authorization_signed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_vehicle_lockout_requests_authorization_agreement","definition":"CREATE INDEX idx_vehicle_lockout_requests_authorization_agreement ON public.vehicle_lockout_requests USING btree (authorization_agreement_id) WHERE (authorization_agreement_id IS NOT NULL)"},{"name":"vehicle_lockout_requests_pkey","definition":"CREATE UNIQUE INDEX vehicle_lockout_requests_pkey ON public.vehicle_lockout_requests USING btree (id)"},{"name":"vehicle_lockout_requests_tenant_status_created_idx","definition":"CREATE INDEX vehicle_lockout_requests_tenant_status_created_idx ON public.vehicle_lockout_requests USING btree (tenant_id, status, created_at DESC)"}],"policies":[{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = vehicle_lockout_requests.tenant_id) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"vehicle_lockout_requests","permissive":"PERMISSIVE","policyname":"vehicle_lockout_requests_member_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = vehicle_lockout_requests.tenant_id) AND (m.status = 'active'::text))))","roles":["authenticated"],"tablename":"vehicle_lockout_requests","permissive":"PERMISSIVE","policyname":"vehicle_lockout_requests_member_update","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = vehicle_lockout_requests.tenant_id) AND (m.status = 'active'::text))))"},{"cmd":"INSERT","qual":null,"roles":["anon","authenticated"],"tablename":"vehicle_lockout_requests","permissive":"PERMISSIVE","policyname":"vehicle_lockout_requests_public_insert","schemaname":"public","with_check":"((tenant_id = 'd60e3c27-73ed-4a5f-a49b-c37636455daf'::uuid) AND (ownership_confirmed = true) AND (authorization_consented = true) AND (NULLIF(btrim(authorization_name), ''::text) IS NOT NULL) AND (char_length(btrim(authorization_name)) <= 120) AND ((char_length(btrim(customer_name)) >= 1) AND (char_length(btrim(customer_name)) <= 120)) AND ((char_length(btrim(phone)) >= 5) AND (char_length(btrim(phone)) <= 40)) AND ((char_length(regexp_replace(phone, '\\D'::text, ''::text, 'g'::text)) >= 7) AND (char_length(regexp_replace(phone, '\\D'::text, ''::text, 'g'::text)) <= 15)) AND ((email IS NULL) OR (char_length(email) <= 254)) AND ((char_length(btrim(service_location)) >= 3) AND (char_length(btrim(service_location)) <= 500)) AND ((city IS NULL) OR (char_length(city) <= 120)) AND ((vehicle_year IS NULL) OR (char_length(vehicle_year) <= 12)) AND ((char_length(btrim(vehicle_make)) >= 1) AND (char_length(btrim(vehicle_make)) <= 80)) AND ((char_length(btrim(vehicle_model)) >= 1) AND (char_length(btrim(vehicle_model)) <= 80)) AND ((vehicle_color IS NULL) OR (char_length(vehicle_color) <= 80)) AND ((license_plate IS NULL) OR (char_length(license_plate) <= 32)) AND ((keys_location IS NULL) OR (char_length(keys_location) <= 240)) AND ((customer_notes IS NULL) OR (char_length(customer_notes) <= 2000)) AND (status = 'requested'::text) AND (payment_status = 'unpaid'::text) AND (source = 'public_site'::text) AND (amount_due IS NULL) AND (amount_paid IS NULL) AND (technician_notes IS NULL) AND (authority_verified = false) AND (authority_verification_method IS NULL) AND (authority_verified_at IS NULL) AND (service_evidence_storage_path IS NULL) AND (completion_acknowledged = false))"}],"triggers":[{"name":"vehicle_lockout_request_record_guard","definition":"CREATE TRIGGER vehicle_lockout_request_record_guard BEFORE INSERT OR UPDATE ON vehicle_lockout_requests FOR EACH ROW EXECUTE FUNCTION vehicle_lockout_request_record_guard()"},{"name":"vehicle_lockout_sync_customer","definition":"CREATE TRIGGER vehicle_lockout_sync_customer AFTER INSERT OR UPDATE OF status, customer_name, phone, email, service_location, city ON vehicle_lockout_requests FOR EACH ROW EXECUTE FUNCTION vehicle_lockout_sync_customer()"}],"constraints":[{"name":"vehicle_lockout_requests_amount_due_check","definition":"CHECK (amount_due IS NULL OR amount_due >= 0::numeric)"},{"name":"vehicle_lockout_requests_amount_paid_check","definition":"CHECK (amount_paid IS NULL OR amount_paid >= 0::numeric)"},{"name":"vehicle_lockout_requests_authority_verification_check","definition":"CHECK (authority_verified = false OR NULLIF(btrim(authority_verification_method), ''::text) IS NOT NULL AND authority_verified_at IS NOT NULL)"},{"name":"vehicle_lockout_requests_authorization_agreement_id_fkey","definition":"FOREIGN KEY (authorization_agreement_id) REFERENCES pending_agreements(id) ON DELETE SET NULL"},{"name":"vehicle_lockout_requests_completed_record_check","definition":"CHECK (status <> 'completed'::text OR authority_verified = true AND NULLIF(btrim(authority_verification_method), ''::text) IS NOT NULL AND authority_verified_at IS NOT NULL AND completion_acknowledged = true AND NULLIF(btrim(completion_acknowledgement_name), ''::text) IS NOT NULL AND completion_acknowledged_at IS NOT NULL)"},{"name":"vehicle_lockout_requests_completion_ack_check","definition":"CHECK (completion_acknowledged = false OR NULLIF(btrim(completion_acknowledgement_name), ''::text) IS NOT NULL AND completion_acknowledged_at IS NOT NULL)"},{"name":"vehicle_lockout_requests_payment_status_check","definition":"CHECK (payment_status = ANY (ARRAY['unpaid'::text, 'partial'::text, 'paid'::text]))"},{"name":"vehicle_lockout_requests_pkey","definition":"PRIMARY KEY (id)"},{"name":"vehicle_lockout_requests_status_check","definition":"CHECK (status = ANY (ARRAY['awaiting_signature'::text, 'agreement_prepared'::text, 'requested'::text, 'en_route'::text, 'on_scene'::text, 'completed'::text, 'canceled'::text]))"},{"name":"vehicle_lockout_requests_tenant_id_fkey","definition":"FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE"}]},{"table":"voice_notes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"title","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"audio_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcription","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcription_status","type":"text","default":"'pending'::text","identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_voice_notes_contact_id","definition":"CREATE INDEX idx_voice_notes_contact_id ON public.voice_notes USING btree (contact_id)"},{"name":"idx_voice_notes_tenant_id","definition":"CREATE INDEX idx_voice_notes_tenant_id ON public.voice_notes USING btree (tenant_id)"},{"name":"idx_voice_notes_user_id","definition":"CREATE INDEX idx_voice_notes_user_id ON public.voice_notes USING btree (user_id)"},{"name":"voice_notes_pkey","definition":"CREATE UNIQUE INDEX voice_notes_pkey ON public.voice_notes USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"voice_notes","permissive":"PERMISSIVE","policyname":"Users create voice notes","schemaname":"public","with_check":"(uid() = user_id)"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = voice_notes.tenant_id))))","roles":["public"],"tablename":"voice_notes","permissive":"PERMISSIVE","policyname":"Users view tenant voice notes","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"voice_notes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"voicemail_audio_cache","schema":"public","columns":[{"name":"cache_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"voice_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rendered_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"audio_storage_path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_sec","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"character_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"use_count","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"last_used_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_voicemail_audio_cache_last_used","definition":"CREATE INDEX idx_voicemail_audio_cache_last_used ON public.voicemail_audio_cache USING btree (last_used_at)"},{"name":"idx_voicemail_audio_cache_rep","definition":"CREATE INDEX idx_voicemail_audio_cache_rep ON public.voicemail_audio_cache USING btree (rep_id)"},{"name":"idx_voicemail_audio_cache_tenant","definition":"CREATE INDEX idx_voicemail_audio_cache_tenant ON public.voicemail_audio_cache USING btree (tenant_org_id)"},{"name":"voicemail_audio_cache_pkey","definition":"CREATE UNIQUE INDEX voicemail_audio_cache_pkey ON public.voicemail_audio_cache USING btree (cache_key)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"voicemail_audio_cache","permissive":"PERMISSIVE","policyname":"tenant_members_read_voicemail_audio_cache","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"voicemail_audio_cache_pkey","definition":"PRIMARY KEY (cache_key)"}]},{"table":"voicemail_boxes","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"ring_group_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"routing_profile_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"greeting_mode","type":"text","default":"'tts'::text","identity":"","not_null":true,"generated":""},{"name":"greeting_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"greeting_audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"max_seconds","type":"integer","default":"120","identity":"","not_null":true,"generated":""},{"name":"transcribe","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"ai_analyze","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"notify_user_ids","type":"uuid[]","default":"'{}'::uuid[]","identity":"","not_null":true,"generated":""},{"name":"notify_emails","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_vm_boxes_profile","definition":"CREATE INDEX idx_vm_boxes_profile ON public.voicemail_boxes USING btree (routing_profile_id) WHERE (routing_profile_id IS NOT NULL)"},{"name":"idx_vm_boxes_ring_group","definition":"CREATE INDEX idx_vm_boxes_ring_group ON public.voicemail_boxes USING btree (ring_group_id) WHERE (ring_group_id IS NOT NULL)"},{"name":"idx_vm_boxes_tenant","definition":"CREATE INDEX idx_vm_boxes_tenant ON public.voicemail_boxes USING btree (tenant_org_id)"},{"name":"idx_vm_boxes_user","definition":"CREATE INDEX idx_vm_boxes_user ON public.voicemail_boxes USING btree (user_id) WHERE (user_id IS NOT NULL)"},{"name":"voicemail_boxes_pkey","definition":"CREATE UNIQUE INDEX voicemail_boxes_pkey ON public.voicemail_boxes USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(is_tenant_member(tenant_org_id) AND is_manager_or_higher(uid(), (tenant_org_id)::uuid))","roles":["authenticated"],"tablename":"voicemail_boxes","permissive":"PERMISSIVE","policyname":"managers_write_vm_boxes","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) AND is_manager_or_higher(uid(), (tenant_org_id)::uuid))"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"voicemail_boxes","permissive":"PERMISSIVE","policyname":"tenant_members_read_vm_boxes","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_vm_boxes_updated","definition":"CREATE TRIGGER trg_vm_boxes_updated BEFORE UPDATE ON voicemail_boxes FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"vm_box_owner_check","definition":"CHECK (((ring_group_id IS NOT NULL)::integer + (routing_profile_id IS NOT NULL)::integer + (user_id IS NOT NULL)::integer) = 1)"},{"name":"voicemail_boxes_greeting_mode_check","definition":"CHECK (greeting_mode = ANY (ARRAY['tts'::text, 'audio'::text]))"},{"name":"voicemail_boxes_max_seconds_check","definition":"CHECK (max_seconds >= 15 AND max_seconds <= 600)"},{"name":"voicemail_boxes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"voicemail_drop_attempts","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"call_mode","type":"text","default":"'unknown'::text","identity":"","not_null":true,"generated":""},{"name":"trigger","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"slot_requested","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"slot_played","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"amd_result","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"silence_watchdog_fired","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"inject_success","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"inject_error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"drop_requested_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"timing_mode","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rep_leg_released","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"source_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"playback_started_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"playback_completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"twilio_update_status","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"pending_drop_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"slot_selection_mode","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"slot_resolved","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"attempt_basis","type":"integer","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_vm_drop_attempts_lead","definition":"CREATE INDEX idx_vm_drop_attempts_lead ON public.voicemail_drop_attempts USING btree (lead_id)"},{"name":"idx_vm_drop_attempts_session","definition":"CREATE INDEX idx_vm_drop_attempts_session ON public.voicemail_drop_attempts USING btree (session_id)"},{"name":"idx_vm_drop_attempts_tenant_created","definition":"CREATE INDEX idx_vm_drop_attempts_tenant_created ON public.voicemail_drop_attempts USING btree (tenant_org_id, created_at DESC)"},{"name":"voicemail_drop_attempts_pkey","definition":"CREATE UNIQUE INDEX voicemail_drop_attempts_pkey ON public.voicemail_drop_attempts USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"voicemail_drop_attempts","permissive":"PERMISSIVE","policyname":"vm_drop_attempts_select_tenant_members","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"voicemail_drop_attempts_call_mode_check","definition":"CHECK (call_mode = ANY (ARRAY['browser'::text, 'cell_bridge'::text, 'external_native'::text, 'unknown'::text]))"},{"name":"voicemail_drop_attempts_pkey","definition":"PRIMARY KEY (id)"},{"name":"voicemail_drop_attempts_trigger_check","definition":"CHECK (trigger = ANY (ARRAY['auto_amd'::text, 'manual_browser'::text, 'silence_watchdog'::text, 'dtmf'::text, 'mobile_link'::text, 'fallback_delay'::text, 'unknown'::text]))"}]},{"table":"voicemail_drop_history","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"phone_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"preset_slot","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"voicemail_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"dropped_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"month_bucket","type":"text","default":"to_char((now() AT TIME ZONE 'UTC'::text), 'YYYY-MM'::text)","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_vm_drop_hist_rep_contact_month","definition":"CREATE INDEX idx_vm_drop_hist_rep_contact_month ON public.voicemail_drop_history USING btree (rep_id, phone_number, month_bucket)"},{"name":"idx_vm_drop_hist_tenant","definition":"CREATE INDEX idx_vm_drop_hist_tenant ON public.voicemail_drop_history USING btree (tenant_org_id, dropped_at DESC)"},{"name":"voicemail_drop_history_pkey","definition":"CREATE UNIQUE INDEX voicemail_drop_history_pkey ON public.voicemail_drop_history USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"voicemail_drop_history","permissive":"PERMISSIVE","policyname":"vm_drop_hist_insert_service","schemaname":"public","with_check":"((rep_id = uid()) AND is_tenant_member(tenant_org_id))"},{"cmd":"SELECT","qual":"((rep_id = uid()) OR is_tenant_member(tenant_org_id))","roles":["authenticated"],"tablename":"voicemail_drop_history","permissive":"PERMISSIVE","policyname":"vm_drop_hist_select_own","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_vm_drop_month_bucket","definition":"CREATE TRIGGER trg_vm_drop_month_bucket BEFORE INSERT OR UPDATE OF dropped_at ON voicemail_drop_history FOR EACH ROW EXECUTE FUNCTION set_vm_drop_month_bucket()"}],"constraints":[{"name":"voicemail_drop_history_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"voicemail_dtmf_tokens","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"active_call_session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"rep_user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"token_hash","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"expires_at","type":"timestamp with time zone","default":null,"identity":"","not_null":true,"generated":""},{"name":"consumed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"consumed_slot","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_vm_dtmf_tokens_expires","definition":"CREATE INDEX idx_vm_dtmf_tokens_expires ON public.voicemail_dtmf_tokens USING btree (expires_at)"},{"name":"idx_vm_dtmf_tokens_rep","definition":"CREATE INDEX idx_vm_dtmf_tokens_rep ON public.voicemail_dtmf_tokens USING btree (rep_user_id)"},{"name":"idx_vm_dtmf_tokens_session","definition":"CREATE INDEX idx_vm_dtmf_tokens_session ON public.voicemail_dtmf_tokens USING btree (active_call_session_id)"},{"name":"voicemail_dtmf_tokens_pkey","definition":"CREATE UNIQUE INDEX voicemail_dtmf_tokens_pkey ON public.voicemail_dtmf_tokens USING btree (id)"},{"name":"voicemail_dtmf_tokens_token_hash_key","definition":"CREATE UNIQUE INDEX voicemail_dtmf_tokens_token_hash_key ON public.voicemail_dtmf_tokens USING btree (token_hash)"}],"policies":[{"cmd":"SELECT","qual":"(rep_user_id = uid())","roles":["authenticated"],"tablename":"voicemail_dtmf_tokens","permissive":"PERMISSIVE","policyname":"rep_read_own_dtmf_tokens","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_voicemail_dtmf_tokens_validate","definition":"CREATE TRIGGER trg_voicemail_dtmf_tokens_validate BEFORE INSERT ON voicemail_dtmf_tokens FOR EACH ROW EXECUTE FUNCTION voicemail_dtmf_tokens_validate()"}],"constraints":[{"name":"voicemail_dtmf_tokens_pkey","definition":"PRIMARY KEY (id)"},{"name":"voicemail_dtmf_tokens_token_hash_key","definition":"UNIQUE (token_hash)"}]},{"table":"voicemail_messages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"voicemail_box_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"ring_group_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"routing_profile_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"caller_number","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"to_number","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_sid","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recording_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_seconds","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcript_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcript_status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"ai_summary","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_sentiment","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ai_topics","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"ai_callback_requested","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"ai_priority","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_read","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"read_by_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"read_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_vm_msgs_box","definition":"CREATE INDEX idx_vm_msgs_box ON public.voicemail_messages USING btree (voicemail_box_id, created_at DESC)"},{"name":"idx_vm_msgs_caller","definition":"CREATE INDEX idx_vm_msgs_caller ON public.voicemail_messages USING btree (caller_number)"},{"name":"idx_vm_msgs_tenant_unread","definition":"CREATE INDEX idx_vm_msgs_tenant_unread ON public.voicemail_messages USING btree (tenant_org_id, is_read, created_at DESC)"},{"name":"voicemail_messages_pkey","definition":"CREATE UNIQUE INDEX voicemail_messages_pkey ON public.voicemail_messages USING btree (id)"},{"name":"voicemail_messages_recording_sid_key","definition":"CREATE UNIQUE INDEX voicemail_messages_recording_sid_key ON public.voicemail_messages USING btree (recording_sid)"}],"policies":[{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) AND is_manager_or_higher(uid(), (tenant_org_id)::uuid))","roles":["authenticated"],"tablename":"voicemail_messages","permissive":"PERMISSIVE","policyname":"managers_delete_vm_msgs","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"voicemail_messages","permissive":"PERMISSIVE","policyname":"tenant_members_read_vm_msgs","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"voicemail_messages","permissive":"PERMISSIVE","policyname":"tenant_members_update_vm_msgs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"voicemail_messages_ai_priority_check","definition":"CHECK ((ai_priority = ANY (ARRAY['low'::text, 'normal'::text, 'high'::text, 'urgent'::text])) OR ai_priority IS NULL)"},{"name":"voicemail_messages_ai_sentiment_check","definition":"CHECK ((ai_sentiment = ANY (ARRAY['positive'::text, 'neutral'::text, 'negative'::text, 'urgent'::text])) OR ai_sentiment IS NULL)"},{"name":"voicemail_messages_pkey","definition":"PRIMARY KEY (id)"},{"name":"voicemail_messages_recording_sid_key","definition":"UNIQUE (recording_sid)"},{"name":"voicemail_messages_transcript_status_check","definition":"CHECK (transcript_status = ANY (ARRAY['pending'::text, 'processing'::text, 'complete'::text, 'failed'::text, 'skipped'::text]))"}]},{"table":"voicemail_preset_slot_config","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"slot","type":"smallint","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":"'First Touch'::text","identity":"","not_null":true,"generated":""},{"name":"rep_guidance","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"script_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"target_seconds","type":"smallint","default":"8","identity":"","not_null":true,"generated":""},{"name":"updated_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_vmpsc_tenant","definition":"CREATE INDEX idx_vmpsc_tenant ON public.voicemail_preset_slot_config USING btree (tenant_org_id, slot)"},{"name":"voicemail_preset_slot_config_pkey","definition":"CREATE UNIQUE INDEX voicemail_preset_slot_config_pkey ON public.voicemail_preset_slot_config USING btree (id)"},{"name":"voicemail_preset_slot_config_tenant_org_id_slot_key","definition":"CREATE UNIQUE INDEX voicemail_preset_slot_config_tenant_org_id_slot_key ON public.voicemail_preset_slot_config USING btree (tenant_org_id, slot)"}],"policies":[{"cmd":"DELETE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships m\n     JOIN user_roles ur ON (((ur.user_id = m.user_id) AND (ur.tenant_id = m.tenant_id))))\n  WHERE ((m.user_id = uid()) AND ((m.tenant_id)::text = voicemail_preset_slot_config.tenant_org_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'Manager'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"voicemail_preset_slot_config","permissive":"PERMISSIVE","policyname":"vmpsc_delete_owner","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"voicemail_preset_slot_config","permissive":"PERMISSIVE","policyname":"vmpsc_insert_owner","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships m\n     JOIN user_roles ur ON (((ur.user_id = m.user_id) AND (ur.tenant_id = m.tenant_id))))\n  WHERE ((m.user_id = uid()) AND ((m.tenant_id)::text = voicemail_preset_slot_config.tenant_org_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'Manager'::app_role, 'GodMode'::app_role]))))))"},{"cmd":"SELECT","qual":"is_tenant_member(tenant_org_id)","roles":["authenticated"],"tablename":"voicemail_preset_slot_config","permissive":"PERMISSIVE","policyname":"vmpsc_select_member","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships m\n     JOIN user_roles ur ON (((ur.user_id = m.user_id) AND (ur.tenant_id = m.tenant_id))))\n  WHERE ((m.user_id = uid()) AND ((m.tenant_id)::text = voicemail_preset_slot_config.tenant_org_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'Manager'::app_role, 'GodMode'::app_role]))))))","roles":["authenticated"],"tablename":"voicemail_preset_slot_config","permissive":"PERMISSIVE","policyname":"vmpsc_update_owner","schemaname":"public","with_check":"(is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (security_active_user_tenant_memberships m\n     JOIN user_roles ur ON (((ur.user_id = m.user_id) AND (ur.tenant_id = m.tenant_id))))\n  WHERE ((m.user_id = uid()) AND ((m.tenant_id)::text = voicemail_preset_slot_config.tenant_org_id) AND (m.status = 'active'::text) AND (ur.role = ANY (ARRAY['Owner'::app_role, 'Tenant Owner'::app_role, 'Admin'::app_role, 'Manager'::app_role, 'GodMode'::app_role]))))))"}],"triggers":[{"name":"trg_touch_vmpsc_updated_at","definition":"CREATE TRIGGER trg_touch_vmpsc_updated_at BEFORE UPDATE ON voicemail_preset_slot_config FOR EACH ROW EXECUTE FUNCTION touch_vmpsc_updated_at()"}],"constraints":[{"name":"voicemail_preset_slot_config_pkey","definition":"PRIMARY KEY (id)"},{"name":"voicemail_preset_slot_config_slot_check","definition":"CHECK (slot >= 1 AND slot <= 4)"},{"name":"voicemail_preset_slot_config_tenant_org_id_slot_key","definition":"UNIQUE (tenant_org_id, slot)"}]},{"table":"voicemail_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"audio_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"audio_duration_sec","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"transcript","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_campaign_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_rep_ids","type":"uuid[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"is_default","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"script_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"external_template_code","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"recommended_for_dropdown","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"owner_user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"direction","type":"text","default":"'outbound'::text","identity":"","not_null":true,"generated":""},{"name":"scope","type":"text","default":"'tenant'::text","identity":"","not_null":true,"generated":""},{"name":"preset_slot","type":"smallint","default":null,"identity":"","not_null":false,"generated":""},{"name":"delivery_mode","type":"text","default":"'cloned_tts'::text","identity":"","not_null":true,"generated":""},{"name":"intro_audio_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"intro_audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outro_audio_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outro_audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"dynamic_slot_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"prosody_profile","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"voice_settings_override","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"intro_transcript","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outro_transcript","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"intro_content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"outro_content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"intro_duration_sec","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"outro_duration_sec","type":"numeric","default":null,"identity":"","not_null":false,"generated":""},{"name":"audio_twilio_compatible","type":"boolean","default":"\nCASE\n    WHEN (delivery_mode = 'hybrid_splice'::text) THEN ((intro_audio_storage_path IS NOT NULL) AND (outro_audio_storage_path IS NOT NULL) AND (intro_audio_storage_path ~* '\\.(mp3|wav|wave|aiff|aif|gsm|ulaw)$'::text) AND (outro_audio_storage_path ~* '\\.(mp3|wav|wave|aiff|aif|gsm|ulaw)$'::text))\n    WHEN (delivery_mode = 'static_audio'::text) THEN ((audio_storage_path IS NOT NULL) AND (audio_storage_path ~* '\\.(mp3|wav|wave|aiff|aif|gsm|ulaw)$'::text))\n    ELSE false\nEND","identity":"","not_null":false,"generated":"s"},{"name":"legacy_intro_audio_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"legacy_outro_audio_storage_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"legacy_intro_audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"legacy_outro_audio_url","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"legacy_intro_content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"legacy_outro_content_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"repaired_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_vm_templates_owner_slot_compat","definition":"CREATE INDEX idx_vm_templates_owner_slot_compat ON public.voicemail_templates USING btree (owner_user_id, preset_slot) WHERE ((scope = 'personal'::text) AND (is_active = true))"},{"name":"idx_vmt_owner","definition":"CREATE INDEX idx_vmt_owner ON public.voicemail_templates USING btree (owner_user_id) WHERE (owner_user_id IS NOT NULL)"},{"name":"idx_vmt_tenant","definition":"CREATE INDEX idx_vmt_tenant ON public.voicemail_templates USING btree (tenant_org_id) WHERE (is_active = true)"},{"name":"idx_vmt_tenant_direction","definition":"CREATE INDEX idx_vmt_tenant_direction ON public.voicemail_templates USING btree (tenant_org_id, direction) WHERE (is_active = true)"},{"name":"uq_vmt_tenant_external_code","definition":"CREATE UNIQUE INDEX uq_vmt_tenant_external_code ON public.voicemail_templates USING btree (tenant_org_id, external_template_code) WHERE (external_template_code IS NOT NULL)"},{"name":"uq_voicemail_owner_preset_slot","definition":"CREATE UNIQUE INDEX uq_voicemail_owner_preset_slot ON public.voicemail_templates USING btree (owner_user_id, preset_slot) WHERE (preset_slot IS NOT NULL)"},{"name":"voicemail_templates_pkey","definition":"CREATE UNIQUE INDEX voicemail_templates_pkey ON public.voicemail_templates USING btree (id)"}],"policies":[{"cmd":"DELETE","qual":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_admin_insert","schemaname":"public","with_check":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())"},{"cmd":"UPDATE","qual":"((is_tenant_member(tenant_org_id) AND is_admin_or_higher(uid(), (tenant_org_id)::uuid)) OR is_system_admin())","roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_admin_update","schemaname":"public","with_check":null},{"cmd":"DELETE","qual":"(is_tenant_member(tenant_org_id) AND (scope = 'personal'::text) AND (owner_user_id = uid()))","roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_personal_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_personal_insert","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) AND (scope = 'personal'::text) AND (owner_user_id = uid()))"},{"cmd":"UPDATE","qual":"(is_tenant_member(tenant_org_id) AND (scope = 'personal'::text) AND (owner_user_id = uid()))","roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_personal_update","schemaname":"public","with_check":"(is_tenant_member(tenant_org_id) AND (scope = 'personal'::text) AND (owner_user_id = uid()))"},{"cmd":"SELECT","qual":"(is_system_admin() OR (is_tenant_member(tenant_org_id) AND ((scope = 'tenant'::text) OR (owner_user_id = uid()) OR is_admin_or_higher(uid(), (tenant_org_id)::uuid))))","roles":["public"],"tablename":"voicemail_templates","permissive":"PERMISSIVE","policyname":"vmt_select_visible","schemaname":"public","with_check":null}],"triggers":[{"name":"trg_validate_voicemail_preset_slot","definition":"CREATE TRIGGER trg_validate_voicemail_preset_slot BEFORE INSERT OR UPDATE ON voicemail_templates FOR EACH ROW EXECUTE FUNCTION validate_voicemail_preset_slot()"},{"name":"trg_vmt_updated_at","definition":"CREATE TRIGGER trg_vmt_updated_at BEFORE UPDATE ON voicemail_templates FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"voicemail_templates_delivery_mode_check","definition":"CHECK (delivery_mode = ANY (ARRAY['cloned_tts'::text, 'static_audio'::text, 'hybrid_splice'::text]))"},{"name":"voicemail_templates_direction_chk","definition":"CHECK (direction = ANY (ARRAY['outbound'::text, 'inbound_greeting'::text]))"},{"name":"voicemail_templates_owner_scope_chk","definition":"CHECK (scope = 'personal'::text AND owner_user_id IS NOT NULL OR scope = 'tenant'::text)"},{"name":"voicemail_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"voicemail_templates_scope_chk","definition":"CHECK (scope = ANY (ARRAY['tenant'::text, 'personal'::text]))"}]},{"table":"website_lead_submissions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_system","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"source_submission_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"integration_key_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'received'::text","identity":"","not_null":true,"generated":""},{"name":"duplicate_of","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"missing_information","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"priority","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ready_for_booking","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"callback_needed","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"raw_payload","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"error","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"request_ip","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_website_lead_submissions_contact","definition":"CREATE INDEX idx_website_lead_submissions_contact ON public.website_lead_submissions USING btree (contact_id)"},{"name":"idx_website_lead_submissions_tenant_created","definition":"CREATE INDEX idx_website_lead_submissions_tenant_created ON public.website_lead_submissions USING btree (tenant_org_id, created_at DESC)"},{"name":"uq_website_lead_submission_idem","definition":"CREATE UNIQUE INDEX uq_website_lead_submission_idem ON public.website_lead_submissions USING btree (tenant_org_id, source_system, source_submission_id)"},{"name":"website_lead_submissions_pkey","definition":"CREATE UNIQUE INDEX website_lead_submissions_pkey ON public.website_lead_submissions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(is_system_admin() OR is_tenant_member(tenant_org_id))","roles":["authenticated"],"tablename":"website_lead_submissions","permissive":"PERMISSIVE","policyname":"Tenant members can view website lead submissions","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"website_lead_submissions_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"weekly_call_report_runs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_start","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"period_end","type":"date","default":null,"identity":"","not_null":true,"generated":""},{"name":"reps_included","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"total_calls","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"appointments_booked","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"emails_sent","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"emails_failed","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"storage_paths","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"status","type":"text","default":"'pending'::text","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_weekly_report_runs_tenant_period","definition":"CREATE INDEX idx_weekly_report_runs_tenant_period ON public.weekly_call_report_runs USING btree (tenant_org_id, period_end DESC)"},{"name":"weekly_call_report_runs_pkey","definition":"CREATE UNIQUE INDEX weekly_call_report_runs_pkey ON public.weekly_call_report_runs USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_owner(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"weekly_call_report_runs","permissive":"PERMISSIVE","policyname":"Tenant owners view weekly report runs","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"weekly_call_report_runs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"weekly_call_report_settings","schema":"public","columns":[{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"enabled","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"owner_email","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"send_day_of_week","type":"integer","default":"6","identity":"","not_null":true,"generated":""},{"name":"send_hour_local","type":"integer","default":"8","identity":"","not_null":true,"generated":""},{"name":"timezone","type":"text","default":"'America/New_York'::text","identity":"","not_null":true,"generated":""},{"name":"include_rep_emails","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"include_owner_combined","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"last_sent_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"weekly_call_report_settings_pkey","definition":"CREATE UNIQUE INDEX weekly_call_report_settings_pkey ON public.weekly_call_report_settings USING btree (tenant_org_id)"}],"policies":[{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"weekly_call_report_settings","permissive":"PERMISSIVE","policyname":"Tenant members view weekly report settings","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_tenant_owner(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"weekly_call_report_settings","permissive":"PERMISSIVE","policyname":"Tenant owners manage weekly report settings","schemaname":"public","with_check":"is_tenant_owner(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_weekly_call_report_settings_updated_at","definition":"CREATE TRIGGER trg_weekly_call_report_settings_updated_at BEFORE UPDATE ON weekly_call_report_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"weekly_call_report_settings_pkey","definition":"PRIMARY KEY (tenant_org_id)"}]},{"table":"workflow_analytics","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"step_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"card_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"exit_path","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"duration_ms","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"session_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_workflow_analytics_created","definition":"CREATE INDEX idx_workflow_analytics_created ON public.workflow_analytics USING btree (created_at DESC)"},{"name":"idx_workflow_analytics_step","definition":"CREATE INDEX idx_workflow_analytics_step ON public.workflow_analytics USING btree (step_id)"},{"name":"idx_workflow_analytics_tenant","definition":"CREATE INDEX idx_workflow_analytics_tenant ON public.workflow_analytics USING btree (tenant_id)"},{"name":"idx_workflow_analytics_user","definition":"CREATE INDEX idx_workflow_analytics_user ON public.workflow_analytics USING btree (user_id)"},{"name":"workflow_analytics_pkey","definition":"CREATE UNIQUE INDEX workflow_analytics_pkey ON public.workflow_analytics USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_analytics","permissive":"PERMISSIVE","policyname":"tenant_members_insert_analytics","schemaname":"public","with_check":"is_tenant_member((tenant_id)::text)"},{"cmd":"SELECT","qual":"is_tenant_member((tenant_id)::text)","roles":["authenticated"],"tablename":"workflow_analytics","permissive":"PERMISSIVE","policyname":"tenant_members_view_analytics","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"workflow_analytics_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_automation_triggers","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"trigger_event","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"from_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"to_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"action_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"action_config","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"conditions","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":false,"generated":""},{"name":"priority","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"execution_count","type":"integer","default":"0","identity":"","not_null":false,"generated":""},{"name":"last_executed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_wat_event","definition":"CREATE INDEX idx_wat_event ON public.workflow_automation_triggers USING btree (trigger_event, is_active)"},{"name":"idx_wat_tenant","definition":"CREATE INDEX idx_wat_tenant ON public.workflow_automation_triggers USING btree (tenant_org_id)"},{"name":"workflow_automation_triggers_pkey","definition":"CREATE UNIQUE INDEX workflow_automation_triggers_pkey ON public.workflow_automation_triggers USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = workflow_automation_triggers.tenant_org_id))))","roles":["authenticated"],"tablename":"workflow_automation_triggers","permissive":"PERMISSIVE","policyname":"Tenant members can manage automation triggers","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = workflow_automation_triggers.tenant_org_id))))"}],"triggers":[],"constraints":[{"name":"workflow_automation_triggers_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_dialogue_stages","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"workflow_id","type":"text","default":"'default'::text","identity":"","not_null":true,"generated":""},{"name":"stage_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_order","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"script_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"prompts","type":"text[]","default":"'{}'::text[]","identity":"","not_null":false,"generated":""},{"name":"next_stage_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"tenancy_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_template","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"derived_from_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"pa_referral_dropdown","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_workflow_dialogue_stages_order","definition":"CREATE INDEX idx_workflow_dialogue_stages_order ON public.workflow_dialogue_stages USING btree (tenant_org_id, workflow_id, stage_order)"},{"name":"idx_workflow_dialogue_stages_tenant","definition":"CREATE INDEX idx_workflow_dialogue_stages_tenant ON public.workflow_dialogue_stages USING btree (tenant_org_id)"},{"name":"idx_workflow_dialogue_stages_workflow","definition":"CREATE INDEX idx_workflow_dialogue_stages_workflow ON public.workflow_dialogue_stages USING btree (tenant_org_id, workflow_id)"},{"name":"idx_workflow_dialogue_template","definition":"CREATE INDEX idx_workflow_dialogue_template ON public.workflow_dialogue_stages USING btree (is_template, tenancy_type) WHERE (is_template = true)"},{"name":"workflow_dialogue_stages_pkey","definition":"CREATE UNIQUE INDEX workflow_dialogue_stages_pkey ON public.workflow_dialogue_stages USING btree (id)"},{"name":"workflow_dialogue_stages_tenant_org_id_workflow_id_stage_or_key","definition":"CREATE UNIQUE INDEX workflow_dialogue_stages_tenant_org_id_workflow_id_stage_or_key ON public.workflow_dialogue_stages USING btree (tenant_org_id, workflow_id, stage_order)"}],"policies":[{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = workflow_dialogue_stages.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["public"],"tablename":"workflow_dialogue_stages","permissive":"PERMISSIVE","policyname":"Tenant admins manage workflow dialogues","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = workflow_dialogue_stages.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE ((user_tenant_memberships.user_id = uid()) AND ((user_tenant_memberships.tenant_id)::text = workflow_dialogue_stages.tenant_org_id))))","roles":["public"],"tablename":"workflow_dialogue_stages","permissive":"PERMISSIVE","policyname":"Users view tenant workflow dialogues","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"workflow_dialogue_stages_pkey","definition":"PRIMARY KEY (id)"},{"name":"workflow_dialogue_stages_tenant_org_id_workflow_id_stage_or_key","definition":"UNIQUE (tenant_org_id, workflow_id, stage_order)"}]},{"table":"workflow_dialogue_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenancy_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"role","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"script_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"prompts","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"next_stage_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_workflow_dialogue_templates_role","definition":"CREATE INDEX idx_workflow_dialogue_templates_role ON public.workflow_dialogue_templates USING btree (role)"},{"name":"idx_workflow_dialogue_templates_tenancy","definition":"CREATE INDEX idx_workflow_dialogue_templates_tenancy ON public.workflow_dialogue_templates USING btree (tenancy_type)"},{"name":"workflow_dialogue_templates_pkey","definition":"CREATE UNIQUE INDEX workflow_dialogue_templates_pkey ON public.workflow_dialogue_templates USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"(is_active = true)","roles":["authenticated"],"tablename":"workflow_dialogue_templates","permissive":"PERMISSIVE","policyname":"Authenticated users can view dialogue templates","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"workflow_dialogue_templates","permissive":"PERMISSIVE","policyname":"platform_admin_manage_dialogue_templates","schemaname":"public","with_check":"is_system_admin(uid())"}],"triggers":[{"name":"update_workflow_dialogue_templates_updated_at","definition":"CREATE TRIGGER update_workflow_dialogue_templates_updated_at BEFORE UPDATE ON workflow_dialogue_templates FOR EACH ROW EXECUTE FUNCTION update_workflow_dialogue_templates_updated_at()"}],"constraints":[{"name":"workflow_dialogue_templates_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"session_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"event_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"stage_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"stage_name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"performed_by","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"outcome","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_workflow_events_created","definition":"CREATE INDEX idx_workflow_events_created ON public.workflow_events USING btree (created_at DESC)"},{"name":"idx_workflow_events_session","definition":"CREATE INDEX idx_workflow_events_session ON public.workflow_events USING btree (session_id)"},{"name":"workflow_events_pkey","definition":"CREATE UNIQUE INDEX workflow_events_pkey ON public.workflow_events USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"workflow_events","permissive":"PERMISSIVE","policyname":"Admins see all workflow events","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(session_id IN ( SELECT workflow_sessions.id\n   FROM workflow_sessions\n  WHERE (workflow_sessions.tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n           FROM security_active_user_tenant_memberships user_tenant_memberships\n          WHERE (user_tenant_memberships.user_id = uid())))))","roles":["public"],"tablename":"workflow_events","permissive":"PERMISSIVE","policyname":"Tenant members see session events","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"workflow_events","permissive":"PERMISSIVE","policyname":"Users insert events from their sessions","schemaname":"public","with_check":"((session_id IN ( SELECT workflow_sessions.id\n   FROM workflow_sessions\n  WHERE (workflow_sessions.user_id = uid()))) AND (performed_by = uid()))"}],"triggers":[],"constraints":[{"name":"workflow_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_publish_events","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_version_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"action","type":"workflow_publish_action","default":null,"identity":"","not_null":true,"generated":""},{"name":"performed_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"actor_role","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"ip_address","type":"inet","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_wpe_created_at","definition":"CREATE INDEX idx_wpe_created_at ON public.workflow_publish_events USING btree (created_at DESC)"},{"name":"idx_wpe_template_id","definition":"CREATE INDEX idx_wpe_template_id ON public.workflow_publish_events USING btree (template_id)"},{"name":"idx_wpe_version_id","definition":"CREATE INDEX idx_wpe_version_id ON public.workflow_publish_events USING btree (template_version_id)"},{"name":"uq_workflow_publish_events_seed","definition":"CREATE UNIQUE INDEX uq_workflow_publish_events_seed ON public.workflow_publish_events USING btree (template_id, template_version_id, action) WHERE (action = 'draft_created'::workflow_publish_action)"},{"name":"workflow_publish_events_pkey","definition":"CREATE UNIQUE INDEX workflow_publish_events_pkey ON public.workflow_publish_events USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_publish_events","permissive":"PERMISSIVE","policyname":"wpe_admin_insert","schemaname":"public","with_check":"is_workflow_template_admin(uid())"},{"cmd":"SELECT","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_publish_events","permissive":"PERMISSIVE","policyname":"wpe_admin_select","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_publish_events","permissive":"PERMISSIVE","policyname":"wpe_tenant_owner_insert","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM workflow_templates t\n  WHERE ((t.id = workflow_publish_events.template_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM workflow_templates t\n  WHERE ((t.id = workflow_publish_events.template_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))","roles":["authenticated"],"tablename":"workflow_publish_events","permissive":"PERMISSIVE","policyname":"wpe_tenant_owner_select","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"workflow_publish_events_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_rebuttals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"workflow_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"objection","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"response","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"one_liner","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_workflow_rebuttals_order","definition":"CREATE INDEX idx_workflow_rebuttals_order ON public.workflow_rebuttals USING btree (tenant_org_id, workflow_id, order_index)"},{"name":"idx_workflow_rebuttals_tenant","definition":"CREATE INDEX idx_workflow_rebuttals_tenant ON public.workflow_rebuttals USING btree (tenant_org_id)"},{"name":"idx_workflow_rebuttals_workflow","definition":"CREATE INDEX idx_workflow_rebuttals_workflow ON public.workflow_rebuttals USING btree (tenant_org_id, workflow_id)"},{"name":"workflow_rebuttals_pkey","definition":"CREATE UNIQUE INDEX workflow_rebuttals_pkey ON public.workflow_rebuttals USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((is_active = true) AND ((tenant_org_id IS NULL) OR (tenant_org_id IN ( SELECT (utm.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships utm\n  WHERE ((utm.user_id = uid()) AND (utm.status = 'active'::text)))) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"workflow_rebuttals","permissive":"PERMISSIVE","policyname":"Tenant members view their rebuttals + globals","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_system_admin(uid())","roles":["public"],"tablename":"workflow_rebuttals","permissive":"PERMISSIVE","policyname":"workflow_rebuttals_godmode","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"SELECT","qual":"((tenant_org_id IS NULL) OR is_tenant_member(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"workflow_rebuttals","permissive":"PERMISSIVE","policyname":"workflow_rebuttals_tenant_member_read","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))","roles":["public"],"tablename":"workflow_rebuttals","permissive":"PERMISSIVE","policyname":"workflow_rebuttals_tenant_owner_manage","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_tenant_owner_or_admin(uid(), (tenant_org_id)::uuid))"}],"triggers":[],"constraints":[{"name":"workflow_rebuttals_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_resolution_parity_logs","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"workflow_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"workflow_source_flag","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"returned_source","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"db_template_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"db_template_version_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"json_card_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"db_card_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"json_rebuttal_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"db_rebuttal_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"json_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"db_hash","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"equal","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"customer_facing_text_equal","type":"boolean","default":null,"identity":"","not_null":false,"generated":""},{"name":"mismatched_card_ids","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"mismatched_choice_next_or_exit","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"db_lint_blocking_count","type":"integer","default":null,"identity":"","not_null":false,"generated":""},{"name":"fallback_used","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"error_message","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"runtime_context","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_wrpl_equal","definition":"CREATE INDEX idx_wrpl_equal ON public.workflow_resolution_parity_logs USING btree (equal)"},{"name":"idx_wrpl_fallback","definition":"CREATE INDEX idx_wrpl_fallback ON public.workflow_resolution_parity_logs USING btree (fallback_used)"},{"name":"idx_wrpl_recent","definition":"CREATE INDEX idx_wrpl_recent ON public.workflow_resolution_parity_logs USING btree (created_at DESC)"},{"name":"idx_wrpl_tenant_workflow_recent","definition":"CREATE INDEX idx_wrpl_tenant_workflow_recent ON public.workflow_resolution_parity_logs USING btree (tenant_org_id, workflow_type, created_at DESC)"},{"name":"idx_wrpl_version","definition":"CREATE INDEX idx_wrpl_version ON public.workflow_resolution_parity_logs USING btree (db_template_version_id)"},{"name":"workflow_resolution_parity_logs_pkey","definition":"CREATE UNIQUE INDEX workflow_resolution_parity_logs_pkey ON public.workflow_resolution_parity_logs USING btree (id)"}],"policies":[{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_resolution_parity_logs","permissive":"PERMISSIVE","policyname":"wrpl_insert_system_admin","schemaname":"public","with_check":"is_system_admin(uid())"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_resolution_parity_logs","permissive":"PERMISSIVE","policyname":"wrpl_insert_tenant_manager","schemaname":"public","with_check":"((tenant_org_id IS NOT NULL) AND is_manager_or_higher(uid(), tenant_org_id))"},{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["authenticated"],"tablename":"workflow_resolution_parity_logs","permissive":"PERMISSIVE","policyname":"wrpl_select_system_admin","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((tenant_org_id IS NOT NULL) AND is_manager_or_higher(uid(), tenant_org_id))","roles":["authenticated"],"tablename":"workflow_resolution_parity_logs","permissive":"PERMISSIVE","policyname":"wrpl_select_tenant_manager","schemaname":"public","with_check":null}],"triggers":[],"constraints":[{"name":"workflow_resolution_parity_logs_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_sessions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"user_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"lead_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"contact_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"current_stage_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"workflow_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"text","default":"'active'::text","identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":false,"generated":""},{"name":"started_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"completed_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_workflow_sessions_lead","definition":"CREATE INDEX idx_workflow_sessions_lead ON public.workflow_sessions USING btree (lead_id)"},{"name":"idx_workflow_sessions_status","definition":"CREATE INDEX idx_workflow_sessions_status ON public.workflow_sessions USING btree (status)"},{"name":"idx_workflow_sessions_tenant","definition":"CREATE INDEX idx_workflow_sessions_tenant ON public.workflow_sessions USING btree (tenant_org_id)"},{"name":"idx_workflow_sessions_user","definition":"CREATE INDEX idx_workflow_sessions_user ON public.workflow_sessions USING btree (user_id)"},{"name":"workflow_sessions_pkey","definition":"CREATE UNIQUE INDEX workflow_sessions_pkey ON public.workflow_sessions USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"is_system_admin(uid())","roles":["public"],"tablename":"workflow_sessions","permissive":"PERMISSIVE","policyname":"Admins see all workflow sessions","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["public"],"tablename":"workflow_sessions","permissive":"PERMISSIVE","policyname":"Tenant members see tenant sessions","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["public"],"tablename":"workflow_sessions","permissive":"PERMISSIVE","policyname":"Users create sessions","schemaname":"public","with_check":"(user_id = uid())"},{"cmd":"UPDATE","qual":"(user_id = uid())","roles":["public"],"tablename":"workflow_sessions","permissive":"PERMISSIVE","policyname":"Users update own sessions","schemaname":"public","with_check":"(user_id = uid())"}],"triggers":[{"name":"workflow_sessions_updated_at","definition":"CREATE TRIGGER workflow_sessions_updated_at BEFORE UPDATE ON workflow_sessions FOR EACH ROW EXECUTE FUNCTION update_workflow_sessions_updated_at()"}],"constraints":[{"name":"workflow_sessions_pkey","definition":"PRIMARY KEY (id)"},{"name":"workflow_sessions_status_check","definition":"CHECK (status = ANY (ARRAY['active'::text, 'paused'::text, 'completed'::text, 'abandoned'::text]))"}]},{"table":"workflow_template_rebuttals","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"template_version_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"objection_label","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"short_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"normal_text","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"long_text","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"tags","type":"text[]","default":"'{}'::text[]","identity":"","not_null":true,"generated":""},{"name":"order_index","type":"integer","default":"0","identity":"","not_null":true,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"linked_card_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"source_rebuttal_id","type":"text","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_wtr_category","definition":"CREATE INDEX idx_wtr_category ON public.workflow_template_rebuttals USING btree (category) WHERE (category IS NOT NULL)"},{"name":"idx_wtr_linked_card","definition":"CREATE INDEX idx_wtr_linked_card ON public.workflow_template_rebuttals USING btree (linked_card_id) WHERE (linked_card_id IS NOT NULL)"},{"name":"idx_wtr_source_rebuttal_id","definition":"CREATE INDEX idx_wtr_source_rebuttal_id ON public.workflow_template_rebuttals USING btree (source_rebuttal_id) WHERE (source_rebuttal_id IS NOT NULL)"},{"name":"idx_wtr_version","definition":"CREATE INDEX idx_wtr_version ON public.workflow_template_rebuttals USING btree (template_version_id)"},{"name":"workflow_template_rebuttals_pkey","definition":"CREATE UNIQUE INDEX workflow_template_rebuttals_pkey ON public.workflow_template_rebuttals USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_template_rebuttals","permissive":"PERMISSIVE","policyname":"wtr_admin_all","schemaname":"public","with_check":"is_workflow_template_admin(uid())"},{"cmd":"SELECT","qual":"((is_active = true) AND (EXISTS ( SELECT 1\n   FROM (workflow_template_versions v\n     JOIN workflow_template_tenant_assignments a ON ((a.template_id = v.template_id)))\n  WHERE ((v.id = workflow_template_rebuttals.template_version_id) AND (v.status = 'published'::workflow_template_version_status) AND (a.is_active = true) AND is_tenant_member(uid(), a.tenant_org_id)))))","roles":["authenticated"],"tablename":"workflow_template_rebuttals","permissive":"PERMISSIVE","policyname":"wtr_member_read_assigned_published","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"(EXISTS ( SELECT 1\n   FROM (workflow_template_versions v\n     JOIN workflow_templates t ON ((t.id = v.template_id)))\n  WHERE ((v.id = workflow_template_rebuttals.template_version_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))","roles":["authenticated"],"tablename":"workflow_template_rebuttals","permissive":"PERMISSIVE","policyname":"wtr_tenant_owner_manage","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM (workflow_template_versions v\n     JOIN workflow_templates t ON ((t.id = v.template_id)))\n  WHERE ((v.id = workflow_template_rebuttals.template_version_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))"}],"triggers":[{"name":"trg_wtr_updated_at","definition":"CREATE TRIGGER trg_wtr_updated_at BEFORE UPDATE ON workflow_template_rebuttals FOR EACH ROW EXECUTE FUNCTION tg_workflow_template_set_updated_at()"}],"constraints":[{"name":"workflow_template_rebuttals_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_template_tenant_assignments","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"pinned_version_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"assigned_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"assigned_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"workflow_type","type":"text","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_wtta_template_id","definition":"CREATE INDEX idx_wtta_template_id ON public.workflow_template_tenant_assignments USING btree (template_id)"},{"name":"idx_wtta_tenant_workflow_type","definition":"CREATE INDEX idx_wtta_tenant_workflow_type ON public.workflow_template_tenant_assignments USING btree (tenant_org_id, workflow_type)"},{"name":"uq_wtta_one_active_per_tenant_workflow_type","definition":"CREATE UNIQUE INDEX uq_wtta_one_active_per_tenant_workflow_type ON public.workflow_template_tenant_assignments USING btree (tenant_org_id, workflow_type) WHERE (is_active = true)"},{"name":"workflow_template_tenant_assignme_tenant_org_id_template_id_key","definition":"CREATE UNIQUE INDEX workflow_template_tenant_assignme_tenant_org_id_template_id_key ON public.workflow_template_tenant_assignments USING btree (tenant_org_id, template_id)"},{"name":"workflow_template_tenant_assignments_pkey","definition":"CREATE UNIQUE INDEX workflow_template_tenant_assignments_pkey ON public.workflow_template_tenant_assignments USING btree (id)"}],"policies":[{"cmd":"ALL","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_template_tenant_assignments","permissive":"PERMISSIVE","policyname":"wtta_admin_all","schemaname":"public","with_check":"is_workflow_template_admin(uid())"},{"cmd":"SELECT","qual":"is_tenant_member(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"workflow_template_tenant_assignments","permissive":"PERMISSIVE","policyname":"wtta_tenant_member_select","schemaname":"public","with_check":null},{"cmd":"ALL","qual":"is_tenant_owner(uid(), tenant_org_id)","roles":["authenticated"],"tablename":"workflow_template_tenant_assignments","permissive":"PERMISSIVE","policyname":"wtta_tenant_owner_manage","schemaname":"public","with_check":"is_tenant_owner(uid(), tenant_org_id)"}],"triggers":[{"name":"trg_wtta_updated_at","definition":"CREATE TRIGGER trg_wtta_updated_at BEFORE UPDATE ON workflow_template_tenant_assignments FOR EACH ROW EXECUTE FUNCTION tg_workflow_template_set_updated_at()"}],"constraints":[{"name":"workflow_template_tenant_assignme_tenant_org_id_template_id_key","definition":"UNIQUE (tenant_org_id, template_id)"},{"name":"workflow_template_tenant_assignments_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"workflow_template_versions","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"template_id","type":"uuid","default":null,"identity":"","not_null":true,"generated":""},{"name":"version_number","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"status","type":"workflow_template_version_status","default":"'draft'::workflow_template_version_status","identity":"","not_null":true,"generated":""},{"name":"cards","type":"jsonb","default":"'[]'::jsonb","identity":"","not_null":true,"generated":""},{"name":"metadata","type":"jsonb","default":"'{}'::jsonb","identity":"","not_null":true,"generated":""},{"name":"lint_report","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"notes","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"published_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"published_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"rollback_parent_version_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_wtv_rollback_parent","definition":"CREATE INDEX idx_wtv_rollback_parent ON public.workflow_template_versions USING btree (rollback_parent_version_id) WHERE (rollback_parent_version_id IS NOT NULL)"},{"name":"idx_wtv_status","definition":"CREATE INDEX idx_wtv_status ON public.workflow_template_versions USING btree (status)"},{"name":"idx_wtv_template_id","definition":"CREATE INDEX idx_wtv_template_id ON public.workflow_template_versions USING btree (template_id)"},{"name":"idx_wtv_template_status","definition":"CREATE INDEX idx_wtv_template_status ON public.workflow_template_versions USING btree (template_id, status)"},{"name":"workflow_template_versions_pkey","definition":"CREATE UNIQUE INDEX workflow_template_versions_pkey ON public.workflow_template_versions USING btree (id)"},{"name":"workflow_template_versions_template_id_version_number_key","definition":"CREATE UNIQUE INDEX workflow_template_versions_template_id_version_number_key ON public.workflow_template_versions USING btree (template_id, version_number)"}],"policies":[{"cmd":"ALL","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_template_versions","permissive":"PERMISSIVE","policyname":"wtv_admin_all","schemaname":"public","with_check":"is_workflow_template_admin(uid())"},{"cmd":"SELECT","qual":"((status = 'published'::workflow_template_version_status) AND (EXISTS ( SELECT 1\n   FROM workflow_template_tenant_assignments a\n  WHERE ((a.template_id = workflow_template_versions.template_id) AND (a.is_active = true) AND is_tenant_member(uid(), a.tenant_org_id)))))","roles":["authenticated"],"tablename":"workflow_template_versions","permissive":"PERMISSIVE","policyname":"wtv_member_read_assigned_published","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_template_versions","permissive":"PERMISSIVE","policyname":"wtv_tenant_owner_insert","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM workflow_templates t\n  WHERE ((t.id = workflow_template_versions.template_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))"},{"cmd":"SELECT","qual":"(EXISTS ( SELECT 1\n   FROM workflow_templates t\n  WHERE ((t.id = workflow_template_versions.template_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), t.owner_tenant_org_id))))","roles":["authenticated"],"tablename":"workflow_template_versions","permissive":"PERMISSIVE","policyname":"wtv_tenant_owner_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM workflow_templates t\n  WHERE ((t.id = workflow_template_versions.template_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))","roles":["authenticated"],"tablename":"workflow_template_versions","permissive":"PERMISSIVE","policyname":"wtv_tenant_owner_update","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM workflow_templates t\n  WHERE ((t.id = workflow_template_versions.template_id) AND (t.scope = 'tenant'::workflow_template_scope) AND (t.owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), t.owner_tenant_org_id))))"}],"triggers":[{"name":"trg_wtv_immutable","definition":"CREATE TRIGGER trg_wtv_immutable BEFORE UPDATE ON workflow_template_versions FOR EACH ROW EXECUTE FUNCTION tg_wtv_immutable_when_published()"}],"constraints":[{"name":"workflow_template_versions_pkey","definition":"PRIMARY KEY (id)"},{"name":"workflow_template_versions_template_id_version_number_key","definition":"UNIQUE (template_id, version_number)"}]},{"table":"workflow_templates","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"slug","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"scope","type":"workflow_template_scope","default":null,"identity":"","not_null":true,"generated":""},{"name":"tenant_type","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_tenant_org_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_active","type":"boolean","default":"true","identity":"","not_null":true,"generated":""},{"name":"current_published_version_id","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"workflow_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_workflow_templates_owner_tenant","definition":"CREATE INDEX idx_workflow_templates_owner_tenant ON public.workflow_templates USING btree (owner_tenant_org_id) WHERE (owner_tenant_org_id IS NOT NULL)"},{"name":"idx_workflow_templates_scope","definition":"CREATE INDEX idx_workflow_templates_scope ON public.workflow_templates USING btree (scope)"},{"name":"idx_workflow_templates_scope_workflow_type","definition":"CREATE INDEX idx_workflow_templates_scope_workflow_type ON public.workflow_templates USING btree (scope, workflow_type)"},{"name":"idx_workflow_templates_tenant_type","definition":"CREATE INDEX idx_workflow_templates_tenant_type ON public.workflow_templates USING btree (tenant_type) WHERE (tenant_type IS NOT NULL)"},{"name":"idx_workflow_templates_tenant_workflow_type","definition":"CREATE INDEX idx_workflow_templates_tenant_workflow_type ON public.workflow_templates USING btree (owner_tenant_org_id, workflow_type) WHERE (owner_tenant_org_id IS NOT NULL)"},{"name":"idx_workflow_templates_workflow_type","definition":"CREATE INDEX idx_workflow_templates_workflow_type ON public.workflow_templates USING btree (workflow_type)"},{"name":"workflow_templates_pkey","definition":"CREATE UNIQUE INDEX workflow_templates_pkey ON public.workflow_templates USING btree (id)"},{"name":"workflow_templates_slug_key","definition":"CREATE UNIQUE INDEX workflow_templates_slug_key ON public.workflow_templates USING btree (slug)"}],"policies":[{"cmd":"DELETE","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_admin_delete","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_admin_insert","schemaname":"public","with_check":"is_workflow_template_admin(uid())"},{"cmd":"SELECT","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_admin_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"is_workflow_template_admin(uid())","roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_admin_update","schemaname":"public","with_check":"is_workflow_template_admin(uid())"},{"cmd":"SELECT","qual":"((scope = ANY (ARRAY['global'::workflow_template_scope, 'tenant_type'::workflow_template_scope])) AND (is_active = true))","roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_authenticated_read_catalog","schemaname":"public","with_check":null},{"cmd":"SELECT","qual":"((scope = 'tenant'::workflow_template_scope) AND (owner_tenant_org_id IS NOT NULL) AND is_tenant_member(uid(), owner_tenant_org_id))","roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_tenant_owner_select","schemaname":"public","with_check":null},{"cmd":"UPDATE","qual":"((scope = 'tenant'::workflow_template_scope) AND (owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), owner_tenant_org_id))","roles":["authenticated"],"tablename":"workflow_templates","permissive":"PERMISSIVE","policyname":"wt_tenant_owner_update","schemaname":"public","with_check":"((scope = 'tenant'::workflow_template_scope) AND (owner_tenant_org_id IS NOT NULL) AND is_tenant_owner(uid(), owner_tenant_org_id))"}],"triggers":[{"name":"trg_wt_updated_at","definition":"CREATE TRIGGER trg_wt_updated_at BEFORE UPDATE ON workflow_templates FOR EACH ROW EXECUTE FUNCTION tg_workflow_template_set_updated_at()"}],"constraints":[{"name":"workflow_templates_pkey","definition":"PRIMARY KEY (id)"},{"name":"workflow_templates_scope_consistency","definition":"CHECK (scope = 'global'::workflow_template_scope AND tenant_type IS NULL AND owner_tenant_org_id IS NULL OR scope = 'tenant_type'::workflow_template_scope AND tenant_type IS NOT NULL AND owner_tenant_org_id IS NULL OR scope = 'tenant'::workflow_template_scope AND owner_tenant_org_id IS NOT NULL)"},{"name":"workflow_templates_slug_key","definition":"UNIQUE (slug)"}]},{"table":"workflow_variables","schema":"public","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"tenant_org_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variable_name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variable_key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"variable_value","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"description","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"example","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"variable_type","type":"variable_type","default":"'text'::variable_type","identity":"","not_null":true,"generated":""},{"name":"scope","type":"variable_scope","default":"'global'::variable_scope","identity":"","not_null":true,"generated":""},{"name":"category","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"idx_workflow_variables_category","definition":"CREATE INDEX idx_workflow_variables_category ON public.workflow_variables USING btree (category)"},{"name":"idx_workflow_variables_scope","definition":"CREATE INDEX idx_workflow_variables_scope ON public.workflow_variables USING btree (scope)"},{"name":"idx_workflow_variables_tenant","definition":"CREATE INDEX idx_workflow_variables_tenant ON public.workflow_variables USING btree (tenant_org_id)"},{"name":"workflow_variables_pkey","definition":"CREATE UNIQUE INDEX workflow_variables_pkey ON public.workflow_variables USING btree (id)"},{"name":"workflow_variables_tenant_org_id_variable_key_key","definition":"CREATE UNIQUE INDEX workflow_variables_tenant_org_id_variable_key_key ON public.workflow_variables USING btree (tenant_org_id, variable_key)"}],"policies":[{"cmd":"DELETE","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = workflow_variables.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["authenticated"],"tablename":"workflow_variables","permissive":"PERMISSIVE","policyname":"Admins can delete tenant variables","schemaname":"public","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"workflow_variables","permissive":"PERMISSIVE","policyname":"Admins can insert tenant variables","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = workflow_variables.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))"},{"cmd":"UPDATE","qual":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = workflow_variables.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))","roles":["authenticated"],"tablename":"workflow_variables","permissive":"PERMISSIVE","policyname":"Admins can update tenant variables","schemaname":"public","with_check":"(EXISTS ( SELECT 1\n   FROM user_roles\n  WHERE ((user_roles.user_id = uid()) AND ((user_roles.tenant_id)::text = workflow_variables.tenant_org_id) AND (user_roles.role = ANY (ARRAY['Owner'::app_role, 'Admin'::app_role, 'GodMode'::app_role])))))"},{"cmd":"SELECT","qual":"(tenant_org_id IN ( SELECT (user_tenant_memberships.tenant_id)::text AS tenant_id\n   FROM security_active_user_tenant_memberships user_tenant_memberships\n  WHERE (user_tenant_memberships.user_id = uid())))","roles":["authenticated"],"tablename":"workflow_variables","permissive":"PERMISSIVE","policyname":"Users can view tenant variables","schemaname":"public","with_check":null}],"triggers":[{"name":"update_workflow_variables_updated_at","definition":"CREATE TRIGGER update_workflow_variables_updated_at BEFORE UPDATE ON workflow_variables FOR EACH ROW EXECUTE FUNCTION update_updated_at_column()"}],"constraints":[{"name":"workflow_variables_pkey","definition":"PRIMARY KEY (id)"},{"name":"workflow_variables_tenant_org_id_variable_key_key","definition":"UNIQUE (tenant_org_id, variable_key)"}]},{"table":"buckets","schema":"storage","columns":[{"name":"id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"owner","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"public","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"avif_autodetection","type":"boolean","default":"false","identity":"","not_null":false,"generated":""},{"name":"file_size_limit","type":"bigint","default":null,"identity":"","not_null":false,"generated":""},{"name":"allowed_mime_types","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"type","type":"buckettype","default":"'STANDARD'::buckettype","identity":"","not_null":true,"generated":""},{"name":"versioning_status","type":"text","default":"'DISABLED'::text","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"bname","definition":"CREATE UNIQUE INDEX bname ON storage.buckets USING btree (name)"},{"name":"buckets_pkey","definition":"CREATE UNIQUE INDEX buckets_pkey ON storage.buckets USING btree (id)"}],"policies":[],"triggers":[{"name":"enforce_bucket_name_length_trigger","definition":"CREATE TRIGGER enforce_bucket_name_length_trigger BEFORE INSERT OR UPDATE OF name ON buckets FOR EACH ROW EXECUTE FUNCTION enforce_bucket_name_length()"},{"name":"protect_buckets_delete","definition":"CREATE TRIGGER protect_buckets_delete BEFORE DELETE ON buckets FOR EACH STATEMENT EXECUTE FUNCTION protect_delete()"}],"constraints":[{"name":"buckets_pkey","definition":"PRIMARY KEY (id)"},{"name":"buckets_versioning_dark_check","definition":"CHECK (versioning_status = 'DISABLED'::text)"},{"name":"buckets_versioning_standard_only_check","definition":"CHECK (type = 'STANDARD'::buckettype OR versioning_status = 'DISABLED'::text)"},{"name":"buckets_versioning_status_check","definition":"CHECK (versioning_status = ANY (ARRAY['DISABLED'::text, 'ENABLED'::text, 'SUSPENDED'::text]))"}]},{"table":"buckets_analytics","schema":"storage","columns":[{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"type","type":"buckettype","default":"'ANALYTICS'::buckettype","identity":"","not_null":true,"generated":""},{"name":"format","type":"text","default":"'ICEBERG'::text","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"deleted_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"buckets_analytics_pkey","definition":"CREATE UNIQUE INDEX buckets_analytics_pkey ON storage.buckets_analytics USING btree (id)"},{"name":"buckets_analytics_unique_name_idx","definition":"CREATE UNIQUE INDEX buckets_analytics_unique_name_idx ON storage.buckets_analytics USING btree (name) WHERE (deleted_at IS NULL)"}],"policies":[],"triggers":[],"constraints":[{"name":"buckets_analytics_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"buckets_vectors","schema":"storage","columns":[{"name":"id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"type","type":"buckettype","default":"'VECTOR'::buckettype","identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"buckets_vectors_pkey","definition":"CREATE UNIQUE INDEX buckets_vectors_pkey ON storage.buckets_vectors USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"buckets_vectors_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"migrations","schema":"storage","columns":[{"name":"id","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"name","type":"character varying(100)","default":null,"identity":"","not_null":true,"generated":""},{"name":"hash","type":"character varying(40)","default":null,"identity":"","not_null":true,"generated":""},{"name":"executed_at","type":"timestamp without time zone","default":"CURRENT_TIMESTAMP","identity":"","not_null":false,"generated":""}],"indexes":[{"name":"migrations_name_key","definition":"CREATE UNIQUE INDEX migrations_name_key ON storage.migrations USING btree (name)"},{"name":"migrations_pkey","definition":"CREATE UNIQUE INDEX migrations_pkey ON storage.migrations USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"migrations_name_key","definition":"UNIQUE (name)"},{"name":"migrations_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"objects","schema":"storage","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"bucket_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner","type":"uuid","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"last_accessed_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"path_tokens","type":"text[]","default":"string_to_array(name, '/'::text)","identity":"","not_null":false,"generated":"s"},{"name":"version","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"owner_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"user_metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"archived_at","type":"timestamp with time zone","default":null,"identity":"","not_null":false,"generated":""},{"name":"is_delete_marker","type":"boolean","default":"false","identity":"","not_null":true,"generated":""},{"name":"is_versioned","type":"boolean","default":"false","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"bucketid_objname","definition":"CREATE UNIQUE INDEX bucketid_objname ON storage.objects USING btree (bucket_id, name)"},{"name":"idx_objects_bucket_id_name","definition":"CREATE INDEX idx_objects_bucket_id_name ON storage.objects USING btree (bucket_id, name COLLATE \"C\")"},{"name":"idx_objects_bucket_id_name_lower","definition":"CREATE INDEX idx_objects_bucket_id_name_lower ON storage.objects USING btree (bucket_id, lower(name) COLLATE \"C\")"},{"name":"name_prefix_search","definition":"CREATE INDEX name_prefix_search ON storage.objects USING btree (name text_pattern_ops)"},{"name":"objects_pkey","definition":"CREATE UNIQUE INDEX objects_pkey ON storage.objects USING btree (id)"}],"policies":[{"cmd":"SELECT","qual":"((bucket_id = 'command-center-visual-witness'::text) AND ((foldername(name))[1] = 'tenant'::text) AND ((foldername(name))[2] IS NOT NULL) AND is_command_agent(uid(), ((foldername(name))[2])::uuid))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Command agents can read visual witness screenshots","schemaname":"storage","with_check":null},{"cmd":"DELETE","qual":"((bucket_id = 'job-photos'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (jobs j\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = uid()) AND (m.tenant_id = j.tenant_id) AND (m.status = 'active'::text))))\n  WHERE (((foldername(objects.name))[1] ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'::text) AND (j.id = ((foldername(objects.name))[1])::uuid))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Tenant members can delete job photos","schemaname":"storage","with_check":null},{"cmd":"UPDATE","qual":"((bucket_id = 'job-photos'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (jobs j\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = uid()) AND (m.tenant_id = j.tenant_id) AND (m.status = 'active'::text))))\n  WHERE (((foldername(objects.name))[1] ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'::text) AND (j.id = ((foldername(objects.name))[1])::uuid))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Tenant members can update job photos","schemaname":"storage","with_check":"((bucket_id = 'job-photos'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (jobs j\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = uid()) AND (m.tenant_id = j.tenant_id) AND (m.status = 'active'::text))))\n  WHERE (((foldername(objects.name))[1] ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'::text) AND (j.id = ((foldername(objects.name))[1])::uuid))))))"},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Tenant members can upload job photos","schemaname":"storage","with_check":"((bucket_id = 'job-photos'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (jobs j\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = uid()) AND (m.tenant_id = j.tenant_id) AND (m.status = 'active'::text))))\n  WHERE (((foldername(objects.name))[1] ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'::text) AND (j.id = ((foldername(objects.name))[1])::uuid))))))"},{"cmd":"SELECT","qual":"((bucket_id = 'job-photos'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM (jobs j\n     JOIN security_active_user_tenant_memberships m ON (((m.user_id = uid()) AND (m.tenant_id = j.tenant_id) AND (m.status = 'active'::text))))\n  WHERE (((foldername(objects.name))[1] ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'::text) AND (j.id = ((foldername(objects.name))[1])::uuid))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Tenant members can view job photos","schemaname":"storage","with_check":null},{"cmd":"DELETE","qual":"((bucket_id = 'voice-notes'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM voice_notes vn\n  WHERE ((vn.user_id = uid()) AND (vn.audio_path = objects.name))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Users can delete own voice notes","schemaname":"storage","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Users can upload own voice notes","schemaname":"storage","with_check":"((bucket_id = 'voice-notes'::text) AND (is_system_admin(uid()) OR ((foldername(name))[1] = (uid())::text)))"},{"cmd":"SELECT","qual":"((bucket_id = 'voice-notes'::text) AND (is_system_admin(uid()) OR (EXISTS ( SELECT 1\n   FROM voice_notes vn\n  WHERE ((vn.user_id = uid()) AND (vn.audio_path = objects.name))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"Users can view own voice notes","schemaname":"storage","with_check":null},{"cmd":"SELECT","qual":"(bucket_id = 'demo-request-logos'::text)","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"authenticated users can read demo request logos","schemaname":"storage","with_check":null},{"cmd":"DELETE","qual":"((bucket_id = 'cafe-menu-media'::text) AND (is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND ((membership.tenant_id)::text = (foldername(objects.name))[1]) AND (COALESCE(membership.status, 'active'::text) = 'active'::text))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"cafe_menu_media_owner_delete","schemaname":"storage","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"cafe_menu_media_owner_insert","schemaname":"storage","with_check":"((bucket_id = 'cafe-menu-media'::text) AND (is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND ((membership.tenant_id)::text = (foldername(objects.name))[1]) AND (COALESCE(membership.status, 'active'::text) = 'active'::text))))))"},{"cmd":"UPDATE","qual":"((bucket_id = 'cafe-menu-media'::text) AND (is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND ((membership.tenant_id)::text = (foldername(objects.name))[1]) AND (COALESCE(membership.status, 'active'::text) = 'active'::text))))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"cafe_menu_media_owner_update","schemaname":"storage","with_check":"((bucket_id = 'cafe-menu-media'::text) AND (is_system_admin(( SELECT uid() AS uid)) OR (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = ( SELECT uid() AS uid)) AND ((membership.tenant_id)::text = (foldername(objects.name))[1]) AND (COALESCE(membership.status, 'active'::text) = 'active'::text))))))"},{"cmd":"SELECT","qual":"(bucket_id = 'cafe-menu-media'::text)","roles":["public"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"cafe_menu_media_public_read","schemaname":"storage","with_check":null},{"cmd":"DELETE","qual":"((bucket_id = 'contact-files'::text) AND ((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = (foldername(objects.name))[1])))) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"contact_files_delete_tenant_members","schemaname":"storage","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"contact_files_insert_tenant_members","schemaname":"storage","with_check":"((bucket_id = 'contact-files'::text) AND ((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = (foldername(objects.name))[1])))) OR is_system_admin(uid())))"},{"cmd":"SELECT","qual":"((bucket_id = 'contact-files'::text) AND ((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = (foldername(objects.name))[1])))) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"contact_files_select_tenant_members","schemaname":"storage","with_check":null},{"cmd":"UPDATE","qual":"((bucket_id = 'contact-files'::text) AND ((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = (foldername(objects.name))[1])))) OR is_system_admin(uid())))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"contact_files_update_tenant_members","schemaname":"storage","with_check":"((bucket_id = 'contact-files'::text) AND ((EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.status = 'active'::text) AND ((m.tenant_id)::text = (foldername(objects.name))[1])))) OR is_system_admin(uid())))"},{"cmd":"INSERT","qual":null,"roles":["anon","authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"public can upload demo request logos","schemaname":"storage","with_check":"((bucket_id = 'demo-request-logos'::text) AND ((foldername(name))[1] IS NOT NULL))"},{"cmd":"SELECT","qual":"((bucket_id = 'tenant-d60e3c27-73ed-4a5f-a49b-c37636455daf'::text) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships m\n  WHERE ((m.user_id = uid()) AND (m.tenant_id = 'd60e3c27-73ed-4a5f-a49b-c37636455daf'::uuid) AND (m.status = 'active'::text)))))","roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"vehicle_lockout_member_proof_read","schemaname":"storage","with_check":null},{"cmd":"INSERT","qual":null,"roles":["authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"vehicle_lockout_member_service_evidence_insert","schemaname":"storage","with_check":"((bucket_id = 'tenant-d60e3c27-73ed-4a5f-a49b-c37636455daf'::text) AND (name ~~ 'service-evidence/%'::text) AND (lower(extension(name)) = ANY (ARRAY['jpg'::text, 'jpeg'::text, 'png'::text, 'webp'::text, 'pdf'::text])) AND (EXISTS ( SELECT 1\n   FROM security_active_user_tenant_memberships membership\n  WHERE ((membership.user_id = uid()) AND (membership.tenant_id = 'd60e3c27-73ed-4a5f-a49b-c37636455daf'::uuid) AND (membership.status = 'active'::text)))))"},{"cmd":"INSERT","qual":null,"roles":["anon","authenticated"],"tablename":"objects","permissive":"PERMISSIVE","policyname":"vehicle_lockout_public_proof_upload","schemaname":"storage","with_check":"((bucket_id = 'tenant-d60e3c27-73ed-4a5f-a49b-c37636455daf'::text) AND (name ~~ 'public-intake/%'::text) AND (lower(extension(name)) = ANY (ARRAY['jpg'::text, 'jpeg'::text, 'png'::text, 'webp'::text, 'pdf'::text])))"}],"triggers":[{"name":"kl_sync_tenant_media_storage_object","definition":"CREATE TRIGGER kl_sync_tenant_media_storage_object AFTER INSERT OR DELETE OR UPDATE ON objects FOR EACH ROW EXECUTE FUNCTION kl_sync_tenant_media_storage_object()"},{"name":"protect_objects_delete","definition":"CREATE TRIGGER protect_objects_delete BEFORE DELETE ON objects FOR EACH STATEMENT EXECUTE FUNCTION protect_delete()"},{"name":"update_objects_updated_at","definition":"CREATE TRIGGER update_objects_updated_at BEFORE UPDATE ON objects FOR EACH ROW EXECUTE FUNCTION storage.update_updated_at_column()"}],"constraints":[{"name":"objects_bucketId_fkey","definition":"FOREIGN KEY (bucket_id) REFERENCES buckets(id)"},{"name":"objects_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"s3_multipart_uploads","schema":"storage","columns":[{"name":"id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"in_progress_size","type":"bigint","default":"0","identity":"","not_null":true,"generated":""},{"name":"upload_signature","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"bucket_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"owner_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"user_metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"metadata","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"idx_multipart_uploads_list","definition":"CREATE INDEX idx_multipart_uploads_list ON storage.s3_multipart_uploads USING btree (bucket_id, key, created_at)"},{"name":"s3_multipart_uploads_pkey","definition":"CREATE UNIQUE INDEX s3_multipart_uploads_pkey ON storage.s3_multipart_uploads USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"s3_multipart_uploads_bucket_id_fkey","definition":"FOREIGN KEY (bucket_id) REFERENCES buckets(id)"},{"name":"s3_multipart_uploads_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"s3_multipart_uploads_parts","schema":"storage","columns":[{"name":"id","type":"uuid","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"upload_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"size","type":"bigint","default":"0","identity":"","not_null":true,"generated":""},{"name":"part_number","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"bucket_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"key","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"etag","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"owner_id","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"s3_multipart_uploads_parts_pkey","definition":"CREATE UNIQUE INDEX s3_multipart_uploads_parts_pkey ON storage.s3_multipart_uploads_parts USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"s3_multipart_uploads_parts_bucket_id_fkey","definition":"FOREIGN KEY (bucket_id) REFERENCES buckets(id)"},{"name":"s3_multipart_uploads_parts_pkey","definition":"PRIMARY KEY (id)"},{"name":"s3_multipart_uploads_parts_upload_id_fkey","definition":"FOREIGN KEY (upload_id) REFERENCES s3_multipart_uploads(id) ON DELETE CASCADE"}]},{"table":"vector_indexes","schema":"storage","columns":[{"name":"id","type":"text","default":"gen_random_uuid()","identity":"","not_null":true,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"bucket_id","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"data_type","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"dimension","type":"integer","default":null,"identity":"","not_null":true,"generated":""},{"name":"distance_metric","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"metadata_configuration","type":"jsonb","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""},{"name":"updated_at","type":"timestamp with time zone","default":"now()","identity":"","not_null":true,"generated":""}],"indexes":[{"name":"vector_indexes_name_bucket_id_idx","definition":"CREATE UNIQUE INDEX vector_indexes_name_bucket_id_idx ON storage.vector_indexes USING btree (name, bucket_id)"},{"name":"vector_indexes_pkey","definition":"CREATE UNIQUE INDEX vector_indexes_pkey ON storage.vector_indexes USING btree (id)"}],"policies":[],"triggers":[],"constraints":[{"name":"vector_indexes_bucket_id_fkey","definition":"FOREIGN KEY (bucket_id) REFERENCES buckets_vectors(id)"},{"name":"vector_indexes_pkey","definition":"PRIMARY KEY (id)"}]},{"table":"schema_migrations","schema":"supabase_migrations","columns":[{"name":"version","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"statements","type":"text[]","default":null,"identity":"","not_null":false,"generated":""},{"name":"name","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"created_by","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"idempotency_key","type":"text","default":null,"identity":"","not_null":false,"generated":""},{"name":"rollback","type":"text[]","default":null,"identity":"","not_null":false,"generated":""}],"indexes":[{"name":"schema_migrations_idempotency_key_key","definition":"CREATE UNIQUE INDEX schema_migrations_idempotency_key_key ON supabase_migrations.schema_migrations USING btree (idempotency_key)"},{"name":"schema_migrations_pkey","definition":"CREATE UNIQUE INDEX schema_migrations_pkey ON supabase_migrations.schema_migrations USING btree (version)"}],"policies":[],"triggers":[],"constraints":[{"name":"schema_migrations_idempotency_key_key","definition":"UNIQUE (idempotency_key)"},{"name":"schema_migrations_pkey","definition":"PRIMARY KEY (version)"}]},{"table":"seed_files","schema":"supabase_migrations","columns":[{"name":"path","type":"text","default":null,"identity":"","not_null":true,"generated":""},{"name":"hash","type":"text","default":null,"identity":"","not_null":true,"generated":""}],"indexes":[{"name":"seed_files_pkey","definition":"CREATE UNIQUE INDEX seed_files_pkey ON supabase_migrations.seed_files USING btree (path)"}],"policies":[],"triggers":[],"constraints":[{"name":"seed_files_pkey","definition":"PRIMARY KEY (path)"}]}],"database":"postgres","routines":[{"name":"current_user_email","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.current_user_email()\n RETURNS text\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\n  select p.email from public.profiles p\n  where p.id = (select auth.uid())\n  limit 1;\n$function$\n","identity_arguments":""},{"name":"current_user_tenant_ids","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.current_user_tenant_ids()\n RETURNS uuid[]\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\n  select coalesce(array_agg(distinct tenant_id), array[]::uuid[])\n  from (\n    select m.tenant_id\n    from public.user_tenant_memberships m\n    where m.user_id = (select auth.uid()) and m.status = 'active'\n    union\n    select r.tenant_id\n    from public.user_roles r\n    where r.user_id = (select auth.uid()) and r.tenant_id is not null\n  ) s;\n$function$\n","identity_arguments":""},{"name":"dedupe_page_view_insert","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.dedupe_page_view_insert()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\ndeclare\n  lock_key bigint;\nbegin\n  lock_key := pg_catalog.hashtextextended(\n    new.user_id::text || '|' || coalesce(new.tenant_id, '') || '|' || new.page_path,\n    0\n  );\n  perform pg_catalog.pg_advisory_xact_lock(lock_key);\n\n  if exists (\n    select 1\n    from public.page_views pv\n    where pv.user_id = new.user_id\n      and coalesce(pv.tenant_id, '') = coalesce(new.tenant_id, '')\n      and pv.page_path = new.page_path\n      and pv.page_title is not distinct from new.page_title\n      and coalesce(pv.metadata, '{}'::jsonb) = coalesce(new.metadata, '{}'::jsonb)\n      and pv.entered_at >= new.entered_at - interval '1 second'\n      and pv.entered_at <= new.entered_at + interval '1 second'\n    order by pv.entered_at desc\n    limit 1\n  ) then\n    return null;\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"expire_stale_user_sessions","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.expire_stale_user_sessions(_cutoff interval DEFAULT '01:00:00'::interval)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\ndeclare\n  expired_count integer := 0;\nbegin\n  if _cutoff is null or _cutoff < interval '5 minutes' then\n    raise exception 'session_expiration_cutoff_too_small';\n  end if;\n\n  update public.user_sessions\n     set is_active = false,\n         ended_at = coalesce(ended_at, last_activity_at, started_at, now()),\n         end_reason = coalesce(nullif(end_reason, ''), 'expired_inactivity')\n   where is_active is true\n     and coalesce(last_activity_at, started_at) < now() - _cutoff;\n\n  get diagnostics expired_count = row_count;\n  return expired_count;\nend;\n$function$\n","identity_arguments":"_cutoff interval"},{"name":"profile_authority_unchanged","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.profile_authority_unchanged(_user_id uuid, _role text, _tenant_org_id text)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  select exists (\n    select 1 from public.profiles p\n    where p.id = _user_id\n      and p.role is not distinct from _role\n      and p.tenant_org_id is not distinct from _tenant_org_id\n  );\n$function$\n","identity_arguments":"_user_id uuid, _role text, _tenant_org_id text"},{"name":"prune_call_lifecycle_debug_events","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.prune_call_lifecycle_debug_events(_retention interval DEFAULT '7 days'::interval)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\ndeclare\n  deleted_count integer := 0;\nbegin\n  if _retention is null or _retention < interval '1 day' then\n    raise exception 'call_lifecycle_debug_retention_too_small';\n  end if;\n\n  delete from public.call_lifecycle_events\n   where created_at < now() - _retention\n     and (\n       event = 'auth.event'\n       or event like 'refresh_blackbox.%'\n     );\n\n  get diagnostics deleted_count = row_count;\n  return deleted_count;\nend;\n$function$\n","identity_arguments":"_retention interval"},{"name":"system_backup_edge_request","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.system_backup_edge_request(p_action text, p_reason text DEFAULT NULL::text, p_source_main_sha text DEFAULT NULL::text, p_force boolean DEFAULT false)\n RETURNS bigint\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'private', 'vault', 'net'\nAS $function$\ndeclare v_token text; v_request_id bigint;\nbegin\n  select decrypted_secret into v_token from vault.decrypted_secrets where name='knocklaunch_system_backup_trigger' limit 1;\n  if v_token is null then raise exception 'system_backup_trigger_secret_missing'; end if;\n  select net.http_post(\n    url:='https://ymntrajfubicyxwwdxxa.supabase.co/functions/v1/system-backup',\n    body:=jsonb_build_object('action',coalesce(nullif(trim(p_action),''),'resume'),'reason',coalesce(nullif(trim(p_reason),''),'scheduled'),'sourceMainSha',nullif(trim(coalesce(p_source_main_sha,'')),''),'force',coalesce(p_force,false)),\n    headers:=jsonb_build_object('Content-Type','application/json','x-backup-token',v_token),timeout_milliseconds:=10000\n  ) into v_request_id;\n  return v_request_id;\nend;\n$function$\n","identity_arguments":"p_action text, p_reason text, p_source_main_sha text, p_force boolean"},{"name":"throttle_membership_access_touch","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.throttle_membership_access_touch()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nbegin\n  if (to_jsonb(new) - 'last_accessed_at') is not distinct from\n     (to_jsonb(old) - 'last_accessed_at')\n     and coalesce(old.last_accessed_at, '-infinity'::timestamptz) >= now() - interval '15 minutes'\n  then return null;\n  end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"throttle_profile_login_touch","schema":"private","definition":"CREATE OR REPLACE FUNCTION private.throttle_profile_login_touch()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nbegin\n  if (to_jsonb(new) - 'last_login' - 'last_login_at') is not distinct from\n     (to_jsonb(old) - 'last_login' - 'last_login_at')\n     and greatest(\n       coalesce(old.last_login_at, '-infinity'::timestamptz),\n       coalesce(old.last_login, '-infinity'::timestamptz)\n     ) >= now() - interval '15 minutes'\n  then return null;\n  end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"_can_view_claim_payment_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public._can_view_claim_payment_status(_tenant uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(auth.uid()) OR EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=auth.uid() AND m.tenant_id=_tenant AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Owner','Tenant Owner','Admin','Manager','PM','GodMode')));\n$function$\n","identity_arguments":"_tenant uuid"},{"name":"_classify_trigger","schema":"public","definition":"CREATE OR REPLACE FUNCTION public._classify_trigger(_name text, _fn text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT CASE\n    WHEN _fn = 'update_updated_at_column' OR _name ILIKE '%updated_at%' THEN 'timestamp'\n    WHEN _fn ILIKE '%audit%' OR _name ILIKE '%audit%' THEN 'audit'\n    WHEN _fn ILIKE '%dnc%' OR _fn ILIKE '%quarantine%' OR _fn ILIKE '%compliance%' OR _fn ILIKE '%prevent_%' THEN 'security'\n    WHEN _fn ILIKE 'auto_%' OR _fn ILIKE '%automation%' OR _fn ILIKE '%dispatch%' OR _fn ILIKE '%send_%' OR _fn ILIKE '%notify%' OR _fn ILIKE '%enqueue%' OR _fn ILIKE '%propagate%' OR _fn ILIKE '%sync%' THEN 'automation'\n    ELSE 'business'\n  END;\n$function$\n","identity_arguments":"_name text, _fn text"},{"name":"_is_admin_caller","schema":"public","definition":"CREATE OR REPLACE FUNCTION public._is_admin_caller()\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$ SELECT public.is_system_admin(auth.uid()); $function$\n","identity_arguments":""},{"name":"_is_manager_or_higher_in_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public._is_manager_or_higher_in_tenant(_tenant uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_manager_or_higher(auth.uid(), _tenant);\n$function$\n","identity_arguments":"_tenant uuid"},{"name":"aaa_validate_tenant_org_id_fn","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.aaa_validate_tenant_org_id_fn()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  -- Allow service role / migrations to bypass (no JWT)\n  IF auth.uid() IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  -- On UPDATE, only validate when tenant_org_id actually changes\n  IF TG_OP = 'UPDATE' AND NEW.tenant_org_id IS NOT DISTINCT FROM OLD.tenant_org_id THEN\n    RETURN NEW;\n  END IF;\n\n  IF NEW.tenant_org_id IS NULL OR NEW.tenant_org_id = '' THEN\n    RAISE EXCEPTION 'unified_contacts.tenant_org_id is required for authenticated writes'\n      USING ERRCODE = 'check_violation';\n  END IF;\n\n  IF NOT EXISTS (\n    SELECT 1 FROM public.tenant_organizations t\n    WHERE t.id::text = NEW.tenant_org_id\n  ) THEN\n    RAISE EXCEPTION 'unified_contacts.tenant_org_id % does not match any tenant_organizations row', NEW.tenant_org_id\n      USING ERRCODE = 'foreign_key_violation';\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"academy_course_completion_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.academy_course_completion_status(_user_id uuid, _course_id uuid)\n RETURNS TABLE(total_lessons integer, completed_lessons integer, progress_percent integer)\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  WITH authorized AS (\n    SELECT (\n      coalesce(auth.role(), '') = 'service_role'\n      OR auth.uid() = _user_id\n      OR public.is_system_admin(auth.uid())\n      OR public.can_view_tenant_member_academy(auth.uid(), _user_id)\n    ) AS ok\n  ),\n  course_lessons AS (\n    SELECT l.id\n    FROM public.academy_units u\n    JOIN public.academy_lessons l ON l.unit_id = u.id\n    WHERE u.course_id = _course_id\n  ),\n  counted AS (\n    SELECT count(*)::int AS total_lessons,\n           count(p.lesson_id)::int AS completed_lessons\n    FROM course_lessons cl\n    LEFT JOIN public.academy_trainee_progress p\n      ON p.lesson_id = cl.id\n     AND p.course_id = _course_id\n     AND p.user_id = _user_id\n     AND p.status = 'completed'\n  )\n  SELECT c.total_lessons,\n         c.completed_lessons,\n         CASE WHEN c.total_lessons = 0 THEN 0\n              ELSE round((c.completed_lessons::numeric / c.total_lessons::numeric) * 100)::int\n         END\n  FROM counted c, authorized a\n  WHERE a.ok;\n$function$\n","identity_arguments":"_user_id uuid, _course_id uuid"},{"name":"academy_course_visible","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.academy_course_visible(p_tenant_org_id text, p_is_published boolean)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  select coalesce(p_is_published,false) and (\n    p_tenant_org_id='00000000-0000-0000-0000-000000000000'\n    or public.is_tenant_member(p_tenant_org_id)\n    or public.is_system_admin(auth.uid())\n  )\n$function$\n","identity_arguments":"p_tenant_org_id text, p_is_published boolean"},{"name":"academy_issue_certificate","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.academy_issue_certificate(_user_id uuid, _course_id uuid, _tenant_org_id text DEFAULT NULL::text, _source text DEFAULT 'course_completion'::text)\n RETURNS uuid\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$ WITH v_course AS (SELECT * FROM public.academy_courses WHERE id = _course_id), v_status AS (SELECT * FROM public.academy_course_completion_status(_user_id, _course_id)), upserted AS (INSERT INTO public.academy_certificates (tenant_org_id, user_id, course_id, certificate_title, score, issued_by, metadata) SELECT COALESCE(_tenant_org_id, c.tenant_org_id), _user_id, _course_id, COALESCE(c.certificate_title, c.title || ' Certificate'), s.progress_percent, auth.uid(), jsonb_build_object('source', _source, 'total_lessons', s.total_lessons, 'completed_lessons', s.completed_lessons, 'course_scope', c.scope, 'tenant_track', c.tenant_track, 'issued_from', 'academy_v2_foundation') FROM v_course c CROSS JOIN v_status s WHERE (auth.uid() = _user_id OR public.is_tenant_owner_for(auth.uid(), COALESCE(_tenant_org_id, c.tenant_org_id)) OR public.is_system_admin(auth.uid())) AND COALESCE(s.total_lessons, 0) > 0 AND COALESCE(s.progress_percent, 0) = 100 ON CONFLICT (tenant_org_id, user_id, course_id) DO UPDATE SET score = EXCLUDED.score, certificate_title = EXCLUDED.certificate_title, metadata = EXCLUDED.metadata, issued_at = now() RETURNING id), rec_user AS (INSERT INTO public.academy_certificate_recipients (certificate_id, recipient_role, recipient_user_id) SELECT u.id, 'user', _user_id FROM upserted u CROSS JOIN v_course c WHERE COALESCE(c.certificate_email_user, true) ON CONFLICT DO NOTHING RETURNING id), rec_owner AS (INSERT INTO public.academy_certificate_recipients (certificate_id, recipient_role) SELECT u.id, 'tenant_owner' FROM upserted u CROSS JOIN v_course c WHERE COALESCE(c.certificate_email_owner, true) ON CONFLICT DO NOTHING RETURNING id) SELECT id FROM upserted $function$\n","identity_arguments":"_user_id uuid, _course_id uuid, _tenant_org_id text, _source text"},{"name":"academy_track_for_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.academy_track_for_tenant(p_tenant_id uuid)\n RETURNS text\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_type text;\n  v_uid uuid := auth.uid();\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       v_uid IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(v_uid), false)\n         AND NOT coalesce(public.is_tenant_member(v_uid, p_tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'academy tenant access denied' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT coalesce(t.tenant_type, o.tenant_type)\n    INTO v_type\n  FROM public.tenants t\n  LEFT JOIN public.tenant_organizations o ON o.id = t.id\n  WHERE t.id = p_tenant_id;\n\n  IF v_type IS NULL THEN\n    SELECT tenant_type INTO v_type\n    FROM public.tenant_organizations\n    WHERE id = p_tenant_id;\n  END IF;\n\n  RETURN public.academy_track_for_type(v_type);\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"academy_track_for_type","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.academy_track_for_type(p_tenant_type text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  select case\n    when upper(coalesce(p_tenant_type,'')) in ('MITIGATION','WATER_MITIGATION','TARPING') then 'mitigation'\n    when upper(coalesce(p_tenant_type,'')) in ('ROOFING','ROOFER','ROOFING_COMPANY','GENERAL_CONTRACTOR','HYBRID_CONTRACTOR','CONTRACTOR') then 'roofing'\n    when upper(coalesce(p_tenant_type,'')) in ('PUBLIC_ADJUSTER','PUBLIC_ADJUSTER_FIRM','PA') then 'public_adjuster'\n    when upper(coalesce(p_tenant_type,'')) in ('REALTOR','REAL_ESTATE','REAL_ESTATE_AGENT') then 'realtor'\n    when upper(coalesce(p_tenant_type,'')) in ('LAWN_CARE','LANDSCAPING') then 'lawn_care'\n    else 'universal'\n  end\n$function$\n","identity_arguments":"p_tenant_type text"},{"name":"adjust_mobile_vendor_inventory","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.adjust_mobile_vendor_inventory(p_tenant_org_id uuid, p_item_id uuid, p_quantity_delta numeric, p_movement_type text, p_event_booking_id uuid DEFAULT NULL::uuid, p_note text DEFAULT NULL::text)\n RETURNS mobile_vendor_inventory_items\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\ndeclare\n  current_item public.mobile_vendor_inventory_items%rowtype;\n  updated_item public.mobile_vendor_inventory_items%rowtype;\n  next_quantity numeric(12,2);\nbegin\n  if p_quantity_delta is null or p_quantity_delta = 0 then\n    raise exception 'Inventory adjustment must be non-zero.';\n  end if;\n  if p_movement_type not in ('purchase','adjustment','event_usage','waste') then\n    raise exception 'Unsupported inventory movement type.';\n  end if;\n\n  select * into current_item\n  from public.mobile_vendor_inventory_items\n  where id = p_item_id and tenant_org_id = p_tenant_org_id\n  for update;\n\n  if not found then\n    raise exception 'Inventory item not found.';\n  end if;\n\n  if p_event_booking_id is not null and not exists (\n    select 1 from public.event_bookings\n    where id = p_event_booking_id\n      and tenant_org_id = p_tenant_org_id::text\n  ) then\n    raise exception 'Event booking does not belong to this workspace.';\n  end if;\n\n  next_quantity := current_item.quantity_on_hand + p_quantity_delta;\n  if next_quantity < 0 then\n    raise exception 'Inventory cannot go below zero.';\n  end if;\n\n  update public.mobile_vendor_inventory_items\n  set quantity_on_hand = next_quantity,\n      updated_at = now()\n  where id = current_item.id\n  returning * into updated_item;\n\n  insert into public.mobile_vendor_inventory_movements (\n    tenant_org_id, inventory_item_id, event_booking_id, movement_type,\n    quantity_delta, balance_after, unit_cost_snapshot, note, created_by, metadata\n  ) values (\n    p_tenant_org_id, current_item.id, p_event_booking_id, p_movement_type,\n    p_quantity_delta, next_quantity, current_item.unit_cost,\n    nullif(trim(coalesce(p_note, '')), ''), auth.uid(),\n    jsonb_build_object('inventory_version','v1')\n  );\n\n  return updated_item;\nend;\n$function$\n","identity_arguments":"p_tenant_org_id uuid, p_item_id uuid, p_quantity_delta numeric, p_movement_type text, p_event_booking_id uuid, p_note text"},{"name":"admin_list_db_triggers","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.admin_list_db_triggers()\n RETURNS TABLE(trigger_name text, table_name text, function_name text, event text, timing text, enabled boolean, enabled_state text, category text, definition text, function_source text)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\nBEGIN\n  IF NOT public._is_admin_caller() THEN\n    RAISE EXCEPTION 'admin only' USING ERRCODE = '42501';\n  END IF;\n\n  RETURN QUERY\n  SELECT\n    t.tgname::text                         AS trigger_name,\n    c.relname::text                        AS table_name,\n    p.proname::text                        AS function_name,\n    CASE\n      WHEN (t.tgtype::int & 4)  = 4  THEN 'INSERT'\n      WHEN (t.tgtype::int & 8)  = 8  THEN 'DELETE'\n      WHEN (t.tgtype::int & 16) = 16 THEN 'UPDATE'\n      WHEN (t.tgtype::int & 32) = 32 THEN 'TRUNCATE'\n      ELSE 'MULTI'\n    END                                     AS event,\n    CASE WHEN (t.tgtype::int & 2) = 2 THEN 'BEFORE' ELSE 'AFTER' END AS timing,\n    (t.tgenabled = 'O')                     AS enabled,\n    CASE t.tgenabled\n      WHEN 'O' THEN 'enabled'\n      WHEN 'D' THEN 'disabled'\n      WHEN 'R' THEN 'replica'\n      WHEN 'A' THEN 'always'\n    END                                     AS enabled_state,\n    public._classify_trigger(t.tgname::text, p.proname::text) AS category,\n    pg_get_triggerdef(t.oid)                AS definition,\n    pg_get_functiondef(p.oid)               AS function_source\n  FROM pg_trigger t\n  JOIN pg_class      c ON c.oid = t.tgrelid\n  JOIN pg_namespace  n ON n.oid = c.relnamespace\n  JOIN pg_proc       p ON p.oid = t.tgfoid\n  WHERE NOT t.tgisinternal\n    AND n.nspname = 'public'\n  ORDER BY c.relname, t.tgname;\nEND;\n$function$\n","identity_arguments":""},{"name":"admin_test_db_trigger","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.admin_test_db_trigger(_trigger_name text, _table_name text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\nDECLARE\n  v_event   text;\n  v_timing  text;\n  v_func    text;\n  v_started timestamptz := clock_timestamp();\n  v_fired   boolean := false;\n  v_error   text;\n  v_detail  text;\nBEGIN\n  IF NOT public._is_admin_caller() THEN\n    RAISE EXCEPTION 'admin only' USING ERRCODE = '42501';\n  END IF;\n\n  -- Look up trigger metadata\n  SELECT\n    CASE\n      WHEN (t.tgtype::int & 4)  = 4  THEN 'INSERT'\n      WHEN (t.tgtype::int & 8)  = 8  THEN 'DELETE'\n      WHEN (t.tgtype::int & 16) = 16 THEN 'UPDATE'\n      ELSE 'MULTI'\n    END,\n    CASE WHEN (t.tgtype::int & 2) = 2 THEN 'BEFORE' ELSE 'AFTER' END,\n    p.proname\n  INTO v_event, v_timing, v_func\n  FROM pg_trigger t\n  JOIN pg_class c     ON c.oid = t.tgrelid\n  JOIN pg_namespace n ON n.oid = c.relnamespace\n  JOIN pg_proc p      ON p.oid = t.tgfoid\n  WHERE n.nspname = 'public'\n    AND c.relname = _table_name\n    AND t.tgname  = _trigger_name\n    AND NOT t.tgisinternal;\n\n  IF v_event IS NULL THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'trigger not found');\n  END IF;\n\n  -- Wrap everything in a savepoint we always release/rollback\n  BEGIN\n    EXECUTE format(\n      'SAVEPOINT trig_test'\n    );\n\n    -- Synthetic operation: copy a row, mutate or insert, see if function ran.\n    -- We use a temporary marker row inserted then deleted inside the savepoint.\n    -- Detection: count tuples written to a per-session marker via temp table.\n    CREATE TEMP TABLE IF NOT EXISTS _trig_test_marker (fired boolean) ON COMMIT DROP;\n    DELETE FROM _trig_test_marker;\n\n    -- Call the trigger function in a controlled way using EXECUTE on the table.\n    -- We attempt event-appropriate no-op against an existing row when possible.\n    BEGIN\n      IF v_event = 'INSERT' THEN\n        EXECUTE format(\n          'INSERT INTO public.%I DEFAULT VALUES RETURNING true',\n          _table_name\n        );\n        v_fired := true;\n      ELSIF v_event = 'UPDATE' THEN\n        EXECUTE format(\n          'UPDATE public.%I SET %I = %I WHERE false',\n          _table_name,\n          (SELECT a.attname\n             FROM pg_attribute a\n             JOIN pg_class c ON c.oid = a.attrelid\n            WHERE c.relname = _table_name\n              AND a.attnum > 0\n              AND NOT a.attisdropped\n            ORDER BY a.attnum\n            LIMIT 1),\n          (SELECT a.attname\n             FROM pg_attribute a\n             JOIN pg_class c ON c.oid = a.attrelid\n            WHERE c.relname = _table_name\n              AND a.attnum > 0\n              AND NOT a.attisdropped\n            ORDER BY a.attnum\n            LIMIT 1)\n        );\n        -- WHERE false → no rows matched, but parser+planner validates the trigger wiring.\n        v_fired := true;\n      ELSIF v_event = 'DELETE' THEN\n        EXECUTE format('DELETE FROM public.%I WHERE false', _table_name);\n        v_fired := true;\n      ELSE\n        v_fired := false;\n        v_detail := 'multi-event trigger; manual review only';\n      END IF;\n    EXCEPTION WHEN OTHERS THEN\n      v_error := SQLERRM;\n      v_detail := SQLSTATE;\n    END;\n\n    -- ALWAYS roll back so production data is untouched\n    EXECUTE 'ROLLBACK TO SAVEPOINT trig_test';\n    EXECUTE 'RELEASE SAVEPOINT trig_test';\n  EXCEPTION WHEN OTHERS THEN\n    v_error := COALESCE(v_error, SQLERRM);\n  END;\n\n  RETURN jsonb_build_object(\n    'ok', v_error IS NULL,\n    'trigger', _trigger_name,\n    'table',   _table_name,\n    'event',   v_event,\n    'timing',  v_timing,\n    'function', v_func,\n    'fired',   v_fired,\n    'rolled_back', true,\n    'duration_ms', extract(milliseconds FROM clock_timestamp() - v_started)::int,\n    'error',   v_error,\n    'detail',  v_detail\n  );\nEND;\n$function$\n","identity_arguments":"_trigger_name text, _table_name text"},{"name":"advance_card_grading_submission","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.advance_card_grading_submission(p_tenant_id uuid, p_submission_id uuid, p_status text)\n RETURNS void\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nbegin\n  if p_status not in ('received','intake_imaging','authentication','grading','encapsulation','qa','ready','shipped','picked_up') then\n    raise exception 'Invalid grading status';\n  end if;\n\n  update public.card_grading_submissions\n     set status = p_status,\n         completed_at = case when p_status in ('shipped','picked_up') then now() else completed_at end,\n         updated_at = now()\n   where id = p_submission_id\n     and tenant_id = p_tenant_id;\n\n  if not found then\n    raise exception 'Submission unavailable';\n  end if;\n\n  update public.card_grading_cards\n     set status = p_status,\n         updated_at = now()\n   where submission_id = p_submission_id\n     and tenant_id = p_tenant_id;\nend;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_submission_id uuid, p_status text"},{"name":"ai_is_tenant_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ai_is_tenant_admin(_tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(auth.uid()) OR EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=auth.uid() AND m.tenant_id=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Owner','Tenant Owner','Admin','GodMode')));\n$function$\n","identity_arguments":"_tenant_id uuid"},{"name":"ai_touch_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ai_touch_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"ai_user_in_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ai_user_in_tenant(_tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$ SELECT public.is_tenant_member(auth.uid(), _tenant_id); $function$\n","identity_arguments":"_tenant_id uuid"},{"name":"append_command_center_receipt","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.append_command_center_receipt(_event_id uuid, _step_id uuid, _receipt_type text, _source text, _status text, _proof_gate text, _external_id text, _source_sha text, _payload jsonb, _idempotency_key text)\n RETURNS command_center_receipts\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _tenant_id uuid;\n  _receipt public.command_center_receipts;\nBEGIN\n  SELECT tenant_id INTO _tenant_id FROM public.command_center_events WHERE id = _event_id;\n  IF _tenant_id IS NULL THEN RAISE EXCEPTION 'mission_not_found'; END IF;\n\n  INSERT INTO public.command_center_receipts (\n    tenant_id, command_center_event_id, mission_step_id, receipt_type, source,\n    status, proof_gate, external_id, source_sha, payload, idempotency_key\n  ) VALUES (\n    _tenant_id, _event_id, _step_id, _receipt_type, _source,\n    _status, _proof_gate, _external_id, _source_sha, coalesce(_payload, '{}'::jsonb), _idempotency_key\n  )\n  ON CONFLICT (idempotency_key) DO UPDATE SET payload = EXCLUDED.payload\n  RETURNING * INTO _receipt;\n\n  UPDATE public.command_center_events\n  SET last_progress_at = now(), lease_expires_at = now() + interval '90 seconds'\n  WHERE id = _event_id;\n  RETURN _receipt;\nEND;\n$function$\n","identity_arguments":"_event_id uuid, _step_id uuid, _receipt_type text, _source text, _status text, _proof_gate text, _external_id text, _source_sha text, _payload jsonb, _idempotency_key text"},{"name":"apply_configured_lead_source_routing","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.apply_configured_lead_source_routing()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare v_tenant_id uuid; v_rule jsonb; v_email text; v_user_id uuid;\nbegin\n  if new.tenant_org_id is null or nullif(btrim(coalesce(new.source, '')), '') is null then return new; end if;\n  begin v_tenant_id := new.tenant_org_id::uuid; exception when invalid_text_representation then return new; end;\n  select coalesce(t.settings->'lead_source_routing'->new.source,t.settings->'lead_source_routing'->lower(new.source)) into v_rule from public.tenants t where t.id = v_tenant_id;\n  v_email := nullif(btrim(coalesce(v_rule->>'assignee_email', '')), '');\n  if v_email is null then return new; end if;\n  select p.id into v_user_id from public.profiles p join public.user_tenant_memberships m on m.user_id=p.id and m.tenant_id=v_tenant_id and m.status='active' where lower(p.email)=lower(v_email) order by m.is_owner desc,m.joined_at nulls last limit 1;\n  if v_user_id is null then new.assigned_to:=null; new.assigned_user:=null; else new.assigned_to:=v_user_id::text; new.assigned_user:=v_user_id::text; end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"apply_lawn_service_exception","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.apply_lawn_service_exception(p_tenant_id uuid, p_visit_id uuid, p_exception_type text, p_note text DEFAULT NULL::text, p_reschedule_date date DEFAULT NULL::date)\n RETURNS uuid\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nDECLARE source_visit public.lawn_service_visits%ROWTYPE; new_visit_id uuid;\nBEGIN\n  SELECT * INTO source_visit FROM public.lawn_service_visits WHERE id = p_visit_id AND tenant_id = p_tenant_id;\n  IF source_visit.id IS NULL THEN RAISE EXCEPTION 'visit not found'; END IF;\n  UPDATE public.lawn_service_visits\n  SET status = CASE WHEN p_reschedule_date IS NULL THEN 'blocked' ELSE 'rescheduled' END,\n      exception_type = p_exception_type,\n      exception_note = p_note\n  WHERE id = source_visit.id;\n  IF p_reschedule_date IS NOT NULL THEN\n    INSERT INTO public.lawn_service_visits (tenant_id, service_plan_id, contact_id, service_date, stop_order, status, assigned_crew_id, metadata)\n    VALUES (p_tenant_id, source_visit.service_plan_id, source_visit.contact_id, p_reschedule_date, source_visit.stop_order, 'scheduled', source_visit.assigned_crew_id, jsonb_build_object('rescheduled_from', source_visit.id, 'reason', p_exception_type))\n    ON CONFLICT (tenant_id, contact_id, service_date) DO UPDATE SET status = 'scheduled', metadata = public.lawn_service_visits.metadata || excluded.metadata\n    RETURNING id INTO new_visit_id;\n  END IF;\n  RETURN coalesce(new_visit_id, source_visit.id);\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_visit_id uuid, p_exception_type text, p_note text, p_reschedule_date date"},{"name":"apply_revocation_to_dnc","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.apply_revocation_to_dnc()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.auto_suppressed THEN\n    INSERT INTO public.dnc_list (tenant_org_id, phone, phone_normalized, source, reason, added_by)\n    VALUES (NEW.tenant_org_id, NEW.phone_number, NEW.phone_normalized,\n      'revocation_' || NEW.channel,\n      'Auto-suppressed via revocation: \"' || COALESCE(NEW.matched_keyword, NEW.trigger_text, 'opt-out') || '\"',\n      'system_revocation_trigger')\n    ON CONFLICT DO NOTHING;\n  END IF;\n  RETURN NEW;\nEND; $function$\n","identity_arguments":""},{"name":"attach_mobile_vendor_loyalty_referral","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.attach_mobile_vendor_loyalty_referral(_tenant_org_id uuid, _friend_member_id uuid, _referral_code text, _landing_ref text DEFAULT NULL::text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_friend public.mobile_vendor_loyalty_members%rowtype;\n  v_referrer public.mobile_vendor_loyalty_members%rowtype;\n  v_referral public.mobile_vendor_loyalty_referrals%rowtype;\n  v_code text := upper(nullif(btrim(coalesce(_referral_code, '')), ''));\nbegin\n  if v_code is null then\n    return jsonb_build_object('ok', true, 'attached', false, 'reason', 'no_referral_code');\n  end if;\n\n  select * into v_friend\n  from public.mobile_vendor_loyalty_members\n  where tenant_org_id = _tenant_org_id and id = _friend_member_id\n  for update;\n  if not found then raise exception 'Loyalty member not found'; end if;\n\n  select * into v_referral\n  from public.mobile_vendor_loyalty_referrals\n  where tenant_org_id = _tenant_org_id and friend_member_id = v_friend.id\n  for update;\n  if found then\n    return jsonb_build_object('ok', true, 'attached', true, 'existing', true, 'referral_id', v_referral.id, 'status', v_referral.status);\n  end if;\n\n  select * into v_referrer\n  from public.mobile_vendor_loyalty_members\n  where tenant_org_id = _tenant_org_id and referral_code = v_code and status = 'active'\n  for update;\n  if not found or v_referrer.id = v_friend.id then\n    return jsonb_build_object('ok', true, 'attached', false, 'reason', 'invalid_referral');\n  end if;\n\n  insert into public.mobile_vendor_loyalty_referrals (\n    tenant_org_id, referrer_member_id, friend_member_id, referral_code,\n    status, welcome_reward_status, metadata\n  ) values (\n    _tenant_org_id, v_referrer.id, v_friend.id, v_code,\n    'joined', 'pending_return',\n    jsonb_build_object('source', 'member_referral_link', 'landing_ref', nullif(btrim(coalesce(_landing_ref, '')), ''))\n  ) returning * into v_referral;\n\n  insert into public.mobile_vendor_loyalty_activity (\n    tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after,\n    points_delta, points_balance_after, source, source_ref, metadata\n  ) values (\n    _tenant_org_id, v_referrer.id, v_referrer.contact_id, 'referral_joined', 0, coalesce(v_referrer.stamp_balance, 0),\n    0, coalesce(v_referrer.points_balance, 0), 'bring_a_friend', v_referral.id::text,\n    jsonb_build_object('friend_member_id', v_friend.id, 'landing_ref', nullif(btrim(coalesce(_landing_ref, '')), ''))\n  );\n\n  return jsonb_build_object('ok', true, 'attached', true, 'existing', false, 'referral_id', v_referral.id, 'status', v_referral.status);\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _friend_member_id uuid, _referral_code text, _landing_ref text"},{"name":"audit_lead_deck_write","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.audit_lead_deck_write()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_changed text[] := NULL;\n  v_uid uuid := NULL;\nBEGIN\n  BEGIN\n    v_uid := auth.uid();\n  EXCEPTION WHEN OTHERS THEN\n    v_uid := NULL;\n  END;\n\n  IF TG_OP = 'UPDATE' THEN\n    SELECT COALESCE(array_agg(key), '{}')\n      INTO v_changed\n    FROM (\n      SELECT key\n      FROM jsonb_each(to_jsonb(NEW)) n\n      JOIN jsonb_each(to_jsonb(OLD)) o USING (key)\n      WHERE n.value IS DISTINCT FROM o.value\n    ) diff;\n  END IF;\n\n  INSERT INTO public.lead_deck_write_audit (\n    op, lead_deck_id, lead_id, tenant_org_id,\n    db_user, auth_uid, source_hint, changed_columns\n  ) VALUES (\n    TG_OP,\n    COALESCE((NEW).id, (OLD).id),\n    COALESCE((NEW).lead_id, (OLD).lead_id),\n    COALESCE((NEW).tenant_org_id, (OLD).tenant_org_id),\n    current_user,\n    v_uid,\n    current_setting('application_name', true),\n    v_changed\n  );\n\n  RETURN COALESCE(NEW, OLD);\nEXCEPTION WHEN OTHERS THEN\n  -- Never block the underlying write because of audit failure.\n  RETURN COALESCE(NEW, OLD);\nEND;\n$function$\n","identity_arguments":""},{"name":"audit_phone_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.audit_phone_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _old text;\n  _new text;\n  _kind text;\n  _target_user uuid;\nBEGIN\n  IF TG_TABLE_NAME = 'profiles' THEN\n    _kind := 'personal_cell';\n    _target_user := NEW.id;\n    _old := OLD.phone;\n    _new := NEW.phone;\n  ELSIF TG_TABLE_NAME = 'rep_verified_caller_ids' THEN\n    _kind := 'forward_to_phone';\n    _target_user := NEW.user_id;\n    _old := OLD.forward_to_phone;\n    _new := NEW.forward_to_phone;\n  ELSE\n    RETURN NEW;\n  END IF;\n\n  IF coalesce(_old,'') = coalesce(_new,'') THEN\n    RETURN NEW;\n  END IF;\n\n  INSERT INTO public.comprehensive_audit_logs\n    (event_type, user_id, success, summary, payload)\n  VALUES (\n    'phone_identity_change',\n    _target_user,\n    true,\n    format('%s changed from %s to %s', _kind, coalesce(_old,'(empty)'), coalesce(_new,'(empty)')),\n    jsonb_build_object(\n      'kind', _kind,\n      'table', TG_TABLE_NAME,\n      'old', _old,\n      'new', _new,\n      'changed_by', auth.uid()\n    )\n  );\n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  -- never block the underlying write because of audit failure\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"audit_trigger_func","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.audit_trigger_func()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_old_data JSONB;\n  v_new_data JSONB;\n  v_user_id UUID;\n  v_tenant_id UUID;\n  v_resource_id TEXT;\nBEGIN\n  BEGIN\n    v_user_id := auth.uid();\n  EXCEPTION WHEN OTHERS THEN\n    v_user_id := NULL;\n  END;\n\n  IF TG_OP = 'DELETE' THEN\n    v_old_data := to_jsonb(OLD);\n    v_new_data := NULL;\n    v_resource_id := OLD.id::TEXT;\n  ELSIF TG_OP = 'INSERT' THEN\n    v_old_data := NULL;\n    v_new_data := to_jsonb(NEW);\n    v_resource_id := NEW.id::TEXT;\n  ELSE\n    v_old_data := to_jsonb(OLD);\n    v_new_data := to_jsonb(NEW);\n    v_resource_id := NEW.id::TEXT;\n  END IF;\n\n  BEGIN\n    IF TG_OP = 'DELETE' THEN\n      v_tenant_id := (v_old_data->>'tenant_org_id')::UUID;\n      IF v_tenant_id IS NULL THEN\n        v_tenant_id := (v_old_data->>'tenant_id')::UUID;\n      END IF;\n    ELSE\n      v_tenant_id := (v_new_data->>'tenant_org_id')::UUID;\n      IF v_tenant_id IS NULL THEN\n        v_tenant_id := (v_new_data->>'tenant_id')::UUID;\n      END IF;\n    END IF;\n  EXCEPTION WHEN OTHERS THEN\n    v_tenant_id := NULL;\n  END;\n\n  INSERT INTO comprehensive_audit_logs (\n    user_id, tenant_id, event_type, event_category, event_action,\n    resource_type, resource_id, old_value, new_value, metadata, severity\n  ) VALUES (\n    v_user_id, v_tenant_id,\n    CASE TG_OP WHEN 'INSERT' THEN 'data_create' WHEN 'UPDATE' THEN 'data_update' WHEN 'DELETE' THEN 'data_delete' END,\n    'data', lower(TG_OP) || '_' || TG_TABLE_NAME,\n    TG_TABLE_NAME, COALESCE(v_resource_id, 'unknown'),\n    v_old_data, v_new_data,\n    jsonb_build_object('table_schema', TG_TABLE_SCHEMA, 'trigger_name', TG_NAME, 'operation', TG_OP),\n    CASE WHEN TG_OP = 'DELETE' THEN 'warn' ELSE 'info' END\n  );\n\n  IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF;\nEND;\n$function$\n","identity_arguments":""},{"name":"auto_create_recontact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.auto_create_recontact()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF NEW.result_status IN ('not_home', 'callback_later', 'interested') THEN\n    INSERT INTO canvassing_recontacts (tenant_org_id, door_id, assigned_to, scheduled_for, reason, priority, created_by, notes)\n    VALUES (\n      NEW.tenant_org_id, NEW.door_id, NEW.user_id,\n      CASE \n        WHEN NEW.result_status = 'interested' THEN NOW() + INTERVAL '2 hours'\n        WHEN NEW.result_status = 'callback_later' THEN NOW() + INTERVAL '4 hours'\n        ELSE NOW() + INTERVAL '1 day'\n      END,\n      NEW.result_status,\n      CASE WHEN NEW.result_status = 'interested' THEN 3 \n           WHEN NEW.result_status = 'callback_later' THEN 2 \n           ELSE 1 END,\n      NEW.user_id, NEW.notes\n    );\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"auto_enroll_academy_onboarding","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.auto_enroll_academy_onboarding()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nbegin\n  if new.status = 'active' and (tg_op = 'INSERT' or old.status is distinct from new.status or old.tenant_id is distinct from new.tenant_id) then\n    perform public.ensure_academy_onboarding_for_member(new.user_id, new.tenant_id, new.invited_by);\n  end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"auto_graduate_lead","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.auto_graduate_lead()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.lead_stage = 'Appointment Set' AND OLD.lead_stage IS DISTINCT FROM 'Appointment Set' THEN\n    NEW.graduated_at := NOW();\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"auto_route_new_roof_lead","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.auto_route_new_roof_lead()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_under_5_years BOOLEAN := false;\n  v_reason TEXT := 'AUTO_ROUTED_<5YR_ROOF';\n  v_queue_lead_id TEXT;\n  v_permit_age_years NUMERIC;\n  v_tenant_type TEXT;\n  v_has_active_claim_or_job BOOLEAN := false;\nBEGIN\n  IF NEW.deleted_at IS NOT NULL THEN\n    RETURN NEW;\n  END IF;\n\n  IF NEW.tenant_org_id IS NOT NULL THEN\n    SELECT tenant_type INTO v_tenant_type\n    FROM public.tenants\n    WHERE id::text = NEW.tenant_org_id;\n    IF v_tenant_type = 'REALTOR' THEN\n      RETURN NEW;\n    END IF;\n  END IF;\n\n  v_has_active_claim_or_job :=\n    NULLIF(TRIM(COALESCE(NEW.claim_stage, '')), '') IS NOT NULL OR\n    NULLIF(TRIM(COALESCE(NEW.jobs_stage, '')), '') IS NOT NULL OR\n    NULLIF(TRIM(COALESCE(NEW.claim_number, '')), '') IS NOT NULL OR\n    NULLIF(TRIM(COALESCE(NEW.claim_number2, '')), '') IS NOT NULL OR\n    NULLIF(TRIM(COALESCE(NEW.claim_number3, '')), '') IS NOT NULL OR\n    NULLIF(TRIM(COALESCE(NEW.claim_number4, '')), '') IS NOT NULL OR\n    NULLIF(TRIM(COALESCE(NEW.job_value, '')), '') IS NOT NULL OR\n    LOWER(COALESCE(NEW.claim_stage, '')) = 'adjuster assigned';\n\n  IF v_has_active_claim_or_job THEN\n    RETURN NEW;\n  END IF;\n\n  IF NEW.roof_permit_finaled_date IS NOT NULL\n     AND NEW.roof_permit_finaled_date > (CURRENT_DATE - INTERVAL '5 years') THEN\n    v_under_5_years := true;\n    v_permit_age_years := EXTRACT(EPOCH FROM (now() - NEW.roof_permit_finaled_date::timestamp)) / (60*60*24*365.25);\n  ELSIF NEW.roof_permit_finaled_date IS NULL\n        AND NEW.property_year_built IS NOT NULL\n        AND NEW.property_year_built > (EXTRACT(YEAR FROM CURRENT_DATE)::int - 5) THEN\n    v_under_5_years := true;\n    v_permit_age_years := EXTRACT(YEAR FROM CURRENT_DATE)::int - NEW.property_year_built;\n  END IF;\n\n  IF NOT v_under_5_years THEN\n    RETURN NEW;\n  END IF;\n\n  v_queue_lead_id := NULLIF(TRIM(COALESCE(NEW.lead_id, '')), '');\n  IF v_queue_lead_id IS NULL THEN\n    v_queue_lead_id := NEW.id::text;\n  END IF;\n\n  INSERT INTO public.new_roofs_queue (\n    lead_id, tenant_org_id, contact_id, name, phone, email,\n    address, city, state, zip,\n    permit_finaled_date, permit_age_years, permit_data,\n    moved_to_queue_at, reason, status, notes\n  ) VALUES (\n    v_queue_lead_id, NEW.tenant_org_id, NEW.id, NEW.name, NEW.phone, NEW.email,\n    NEW.address, NEW.city, NEW.state, NEW.zip,\n    NEW.roof_permit_finaled_date, v_permit_age_years, NEW.permit_data,\n    now(), v_reason, 'queued', 'Auto-routed: roof under 5 years old'\n  )\n  ON CONFLICT (lead_id, tenant_org_id) DO UPDATE SET\n    contact_id = COALESCE(EXCLUDED.contact_id, new_roofs_queue.contact_id),\n    permit_finaled_date = COALESCE(EXCLUDED.permit_finaled_date, new_roofs_queue.permit_finaled_date),\n    permit_age_years = COALESCE(EXCLUDED.permit_age_years, new_roofs_queue.permit_age_years),\n    permit_data = COALESCE(EXCLUDED.permit_data, new_roofs_queue.permit_data),\n    updated_at = now();\n\n  NEW.archived_at := COALESCE(NEW.archived_at, now());\n  NEW.status := 'New Roof Queue';\n  NEW.lead_stage := 'New Roof Queue';\n  NEW.updated_at := now();\n\n  UPDATE public.lead_deck\n  SET archived_at = COALESCE(archived_at, now()),\n      status = 'New Roof Queue',\n      lead_stage = 'New Roof Queue',\n      updated_at = now()\n  WHERE tenant_org_id = NEW.tenant_org_id\n    AND lead_id = v_queue_lead_id\n    AND deleted_at IS NULL;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"auto_send_portal_welcome_on_signed_agreement","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.auto_send_portal_welcome_on_signed_agreement()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _portal_token TEXT;\n  _existing_link RECORD;\n  _contact RECORD;\n  _tenant RECORD;\n  _company_name TEXT;\n  _vertical TEXT;\n  _portal_url TEXT;\n  _base_url TEXT := 'https://app.knocklaunch.app';\n  _service_key TEXT;\n  _supabase_url TEXT;\n  _auto_send BOOLEAN := true;\n  _request_id BIGINT;\nBEGIN\n  -- Only fire when transitioning to signed\n  IF NEW.signed_at IS NULL THEN\n    RETURN NEW;\n  END IF;\n  IF OLD.signed_at IS NOT NULL THEN\n    RETURN NEW;\n  END IF;\n\n  -- Need contact + email + tenant\n  IF NEW.contact_id IS NULL OR NEW.recipient_email IS NULL OR NEW.tenant_id IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  -- Look up contact\n  SELECT id, full_name, archived_at, portal_token\n    INTO _contact\n    FROM public.unified_contacts\n   WHERE id = NEW.contact_id\n   LIMIT 1;\n\n  IF _contact IS NULL OR _contact.archived_at IS NOT NULL THEN\n    RETURN NEW;\n  END IF;\n\n  -- Look up tenant + check opt-out flag in tenants.settings\n  SELECT id,\n         COALESCE(company_dba_name, company_legal_name, name) AS display_name,\n         tenant_type,\n         COALESCE((settings->>'auto_send_portal_welcome')::boolean, true) AS auto_flag\n    INTO _tenant\n    FROM public.tenants\n   WHERE id::text = NEW.tenant_id::text\n   LIMIT 1;\n\n  IF _tenant IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  IF _tenant.auto_flag = false THEN\n    RETURN NEW;\n  END IF;\n\n  _company_name := COALESCE(_tenant.display_name, 'Your team');\n\n  -- Map tenant_type -> vertical (mirrors customer-portal edge function)\n  IF UPPER(COALESCE(_tenant.tenant_type, '')) LIKE '%PUBLIC%'\n     OR UPPER(COALESCE(_tenant.tenant_type, '')) LIKE '%ADJUSTER%' THEN\n    _vertical := 'public_adjuster';\n  ELSIF UPPER(COALESCE(_tenant.tenant_type, '')) LIKE '%ROOF%' THEN\n    _vertical := 'roofer';\n  ELSE\n    _vertical := 'mitigation';\n  END IF;\n\n  -- Reuse existing active portal link or mint a new one\n  SELECT token INTO _existing_link\n    FROM public.portal_links\n   WHERE contact_id = NEW.contact_id\n     AND is_active = true\n   ORDER BY created_at DESC\n   LIMIT 1;\n\n  IF _existing_link IS NOT NULL THEN\n    _portal_token := _existing_link.token;\n  ELSE\n    _portal_token := public.generate_portal_token() || public.generate_portal_token();\n    INSERT INTO public.portal_links (contact_id, tenant_org_id, token, expires_at, created_by, is_active)\n    VALUES (NEW.contact_id, NEW.tenant_id::text, _portal_token, NULL, NEW.sent_by_user_id, true);\n  END IF;\n\n  -- Mirror token onto contact for quick lookup\n  IF _contact.portal_token IS DISTINCT FROM _portal_token THEN\n    UPDATE public.unified_contacts\n       SET portal_token = _portal_token\n     WHERE id = NEW.contact_id;\n  END IF;\n\n  _portal_url := _base_url || '/portal/' || _portal_token;\n\n  -- Read vaulted service role key + project URL to call send-transactional-email\n  BEGIN\n    SELECT decrypted_secret INTO _service_key\n      FROM vault.decrypted_secrets\n     WHERE name = 'email_queue_service_role_key'\n     LIMIT 1;\n  EXCEPTION WHEN OTHERS THEN\n    _service_key := NULL;\n  END;\n\n  BEGIN\n    SELECT decrypted_secret INTO _supabase_url\n      FROM vault.decrypted_secrets\n     WHERE name = 'project_url'\n     LIMIT 1;\n  EXCEPTION WHEN OTHERS THEN\n    _supabase_url := NULL;\n  END;\n\n  -- Hardcoded fallback URL based on project ref (vault may not have project_url)\n  IF _supabase_url IS NULL OR _supabase_url = '' THEN\n    _supabase_url := 'https://ymntrajfubicyxwwdxxa.supabase.co';\n  END IF;\n\n  IF _service_key IS NULL OR _service_key = '' THEN\n    -- Without service key we cannot invoke the function; skip silently\n    RAISE NOTICE 'auto_send_portal_welcome: no service key in vault, skipping email';\n    RETURN NEW;\n  END IF;\n\n  -- Fire and forget — pg_net is async; signing latency is unaffected\n  SELECT net.http_post(\n    url := _supabase_url || '/functions/v1/send-transactional-email',\n    headers := jsonb_build_object(\n      'Content-Type', 'application/json',\n      'Authorization', 'Bearer ' || _service_key\n    ),\n    body := jsonb_build_object(\n      'templateName', 'portal-welcome',\n      'recipientEmail', NEW.recipient_email,\n      'idempotencyKey', 'portal-welcome-' || NEW.id::text,\n      'templateData', jsonb_build_object(\n        'recipientName', COALESCE(NEW.recipient_name, _contact.full_name, ''),\n        'companyName', _company_name,\n        'portalUrl', _portal_url,\n        'vertical', _vertical\n      )\n    )\n  ) INTO _request_id;\n\n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  -- Never block agreement signing on email/portal failure\n  RAISE NOTICE 'auto_send_portal_welcome failed: %', SQLERRM;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"auto_stamp_claim_check_issued","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.auto_stamp_claim_check_issued()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.check_issued_at IS NULL THEN\n    IF NEW.settlement_date IS NOT NULL THEN\n      NEW.check_issued_at := NEW.settlement_date::timestamptz;\n    ELSIF NEW.settlement_amount IS NOT NULL AND NEW.settlement_amount > 0 THEN\n      NEW.check_issued_at := now();\n    END IF;\n  END IF;\n\n  IF NEW.check_issued_amount IS NULL AND NEW.settlement_amount IS NOT NULL THEN\n    NEW.check_issued_amount := NEW.settlement_amount;\n  END IF;\n\n  IF NEW.check_issued_at IS NOT NULL AND NEW.check_issued_by IS NULL THEN\n    NEW.check_issued_by := auth.uid();\n  END IF;\n\n  IF NEW.settlement_date IS NULL\n     AND (NEW.settlement_amount IS NULL OR NEW.settlement_amount = 0)\n     AND NEW.check_received_by_homeowner_at IS NULL THEN\n    NEW.check_issued_at := NULL;\n    NEW.check_issued_amount := NULL;\n    NEW.check_issued_by := NULL;\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"automation_dispatch_on_update","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.automation_dispatch_on_update()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_changed_field TEXT;\n  v_trigger_type TEXT;\n  v_supabase_url TEXT;\n  v_anon_key TEXT;\nBEGIN\n  -- Determine what changed\n  IF OLD.status IS DISTINCT FROM NEW.status THEN\n    v_changed_field := 'status';\n    v_trigger_type := 'status_change';\n  ELSIF OLD.lead_stage IS DISTINCT FROM NEW.lead_stage THEN\n    v_changed_field := 'lead_stage';\n    v_trigger_type := 'stage_change';\n  ELSIF OLD.jobs_stage IS DISTINCT FROM NEW.jobs_stage THEN\n    v_changed_field := 'jobs_stage';\n    v_trigger_type := 'stage_change';\n  ELSIF OLD.claim_stage IS DISTINCT FROM NEW.claim_stage THEN\n    v_changed_field := 'claim_stage';\n    v_trigger_type := 'stage_change';\n  ELSIF OLD.assigned_to IS DISTINCT FROM NEW.assigned_to THEN\n    v_changed_field := 'assigned_to';\n    v_trigger_type := 'assignment_change';\n  ELSE\n    -- No automation-relevant field changed\n    RETURN NEW;\n  END IF;\n\n  -- Get Supabase URL from vault or config\n  v_supabase_url := current_setting('app.settings.supabase_url', true);\n  v_anon_key := current_setting('app.settings.anon_key', true);\n\n  -- Only fire if we have config (won't fire in dev without settings)\n  IF v_supabase_url IS NOT NULL AND v_anon_key IS NOT NULL THEN\n    PERFORM extensions.http_post(\n      url := v_supabase_url || '/functions/v1/pipeline-automation',\n      headers := jsonb_build_object(\n        'Content-Type', 'application/json',\n        'Authorization', 'Bearer ' || v_anon_key\n      ),\n      body := jsonb_build_object(\n        'action', 'trigger',\n        'event', jsonb_build_object(\n          'type', v_trigger_type,\n          'contactId', NEW.id::text,\n          'tenantId', COALESCE(NEW.tenant_org_id, ''),\n          'field', v_changed_field,\n          'oldValue', CASE v_changed_field\n            WHEN 'status' THEN OLD.status\n            WHEN 'lead_stage' THEN OLD.lead_stage\n            WHEN 'jobs_stage' THEN OLD.jobs_stage\n            WHEN 'claim_stage' THEN OLD.claim_stage\n            WHEN 'assigned_to' THEN OLD.assigned_to\n          END,\n          'newValue', CASE v_changed_field\n            WHEN 'status' THEN NEW.status\n            WHEN 'lead_stage' THEN NEW.lead_stage\n            WHEN 'jobs_stage' THEN NEW.jobs_stage\n            WHEN 'claim_stage' THEN NEW.claim_stage\n            WHEN 'assigned_to' THEN NEW.assigned_to\n          END\n        )\n      )\n    );\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"block_mutation_append_only","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.block_mutation_append_only()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  RAISE EXCEPTION\n    'Table %.% is append-only. Mutations and deletions are not permitted. Use supersession instead.',\n    TG_TABLE_SCHEMA, TG_TABLE_NAME\n    USING ERRCODE = 'insufficient_privilege';\nEND;\n$function$\n","identity_arguments":""},{"name":"bootstrap_roofing_project_ops","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.bootstrap_roofing_project_ops()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  is_roofing boolean;\n  next_phase text;\n  next_funding text;\nbegin\n  select exists (\n    select 1 from public.tenants t\n    where t.id = new.tenant_id\n      and upper(replace(coalesce(t.tenant_type, ''), ' ', '_')) = 'ROOFING_COMPANY'\n  ) into is_roofing;\n  if not is_roofing then return new; end if;\n\n  next_phase := case\n    when new.status in ('scheduled','acknowledged','dispatched') then 'scheduled'\n    when new.status in ('on_site','in_progress') then 'production'\n    when new.status in ('crew_completed','pm_verifying','pm_verified','manager_review','manager_approved','payroll_ready','submitted','completed','verified') then 'closeout'\n    when new.status = 'paid' then 'complete'\n    else 'preproduction'\n  end;\n  next_funding := case when coalesce(new.funding_type, 'retail') = 'insurance' then 'insurance' else 'retail' end;\n\n  insert into public.roofing_project_ops (\n    tenant_id, job_id, contact_id, project_phase, funding_type,\n    insurance_status, financing_status\n  ) values (\n    new.tenant_id, new.id, new.contact_id, next_phase, next_funding,\n    case when next_funding = 'insurance' then 'intake' else 'not_applicable' end,\n    case when coalesce(new.financing_mode, 'none') = 'none' then 'not_applicable' else 'draft' end\n  )\n  on conflict (job_id) do update set\n    contact_id = coalesce(excluded.contact_id, public.roofing_project_ops.contact_id),\n    project_phase = excluded.project_phase,\n    funding_type = excluded.funding_type,\n    updated_at = now();\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"business_apply_opportunity_transition","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_apply_opportunity_transition(_opportunity_id uuid, _dimension text, _to_state text, _reason_code text, _metadata jsonb DEFAULT '{}'::jsonb)\n RETURNS business_opportunities\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  o public.business_opportunities%rowtype;\n  final_o public.business_opportunities%rowtype;\n  current_state text;\n  allowed_states text[];\n  proposal_hours integer;\n  deposit_hours integer;\n  balance_hours integer;\nbegin\n  select * into o from public.business_opportunities where id = _opportunity_id for update;\n  if not found then raise exception 'business_opportunity_not_found'; end if;\n  perform public.business_engine_assert_access(o.tenant_id);\n\n  if nullif(btrim(coalesce(_reason_code, '')), '') is null then\n    raise exception 'business_transition_reason_required';\n  end if;\n  if _dimension not in ('lifecycle','proposal','payment','fulfillment') then\n    raise exception 'business_transition_dimension_invalid:%', _dimension;\n  end if;\n\n  current_state := case _dimension\n    when 'lifecycle' then o.lifecycle_state\n    when 'proposal' then o.proposal_state\n    when 'payment' then o.payment_state\n    when 'fulfillment' then o.fulfillment_state\n  end;\n\n  if current_state = _to_state then\n    return o;\n  end if;\n\n  allowed_states := case\n    when _dimension = 'lifecycle' and current_state = 'captured' then array['qualified','won','lost','cancelled']\n    when _dimension = 'lifecycle' and current_state = 'qualified' then array['won','lost','cancelled']\n    when _dimension = 'lifecycle' and current_state = 'won' then array['cancelled']\n    when _dimension = 'proposal' and current_state = 'not_started' then array['draft','sent','accepted','void']\n    when _dimension = 'proposal' and current_state = 'draft' then array['sent','accepted','void']\n    when _dimension = 'proposal' and current_state = 'sent' then array['accepted','declined','void']\n    when _dimension = 'proposal' and current_state = 'declined' then array['draft','void']\n    when _dimension = 'proposal' and current_state = 'accepted' then array['void']\n    when _dimension = 'payment' and current_state = 'not_required' then array['deposit_due','balance_due','paid','void']\n    when _dimension = 'payment' and current_state = 'deposit_due' then array['deposit_paid','deposit_overdue','balance_due','void']\n    when _dimension = 'payment' and current_state = 'deposit_overdue' then array['deposit_paid','balance_due','void']\n    when _dimension = 'payment' and current_state = 'deposit_paid' then array['balance_due','paid','refunded','void']\n    when _dimension = 'payment' and current_state = 'balance_due' then array['paid','balance_overdue','void']\n    when _dimension = 'payment' and current_state = 'balance_overdue' then array['paid','void']\n    when _dimension = 'payment' and current_state = 'paid' then array['refunded']\n    when _dimension = 'fulfillment' and current_state = 'not_scheduled' then array['scheduled','in_progress','completed','cancelled']\n    when _dimension = 'fulfillment' and current_state = 'scheduled' then array['in_progress','completed','cancelled']\n    when _dimension = 'fulfillment' and current_state = 'in_progress' then array['completed','cancelled']\n    else array[]::text[]\n  end;\n\n  if not (_to_state = any(allowed_states)) then\n    raise exception 'business_transition_not_allowed:%:%->%', _dimension, current_state, _to_state;\n  end if;\n\n  select p.proposal_followup_hours, p.deposit_due_hours, p.balance_due_hours\n    into proposal_hours, deposit_hours, balance_hours\n    from public.business_workflow_policies p where p.tenant_id = o.tenant_id;\n  proposal_hours := coalesce(proposal_hours, 48);\n  deposit_hours := coalesce(deposit_hours, 72);\n  balance_hours := coalesce(balance_hours, 24);\n\n  update public.business_opportunities\n     set lifecycle_state = case when _dimension = 'lifecycle' then _to_state else lifecycle_state end,\n         proposal_state = case when _dimension = 'proposal' then _to_state else proposal_state end,\n         payment_state = case when _dimension = 'payment' then _to_state else payment_state end,\n         fulfillment_state = case when _dimension = 'fulfillment' then _to_state else fulfillment_state end,\n         proposal_sent_at = case when _dimension = 'proposal' and _to_state = 'sent' then coalesce(proposal_sent_at, now()) else proposal_sent_at end,\n         proposal_followup_due_at = case when _dimension = 'proposal' and _to_state = 'sent' then coalesce(proposal_followup_due_at, now() + make_interval(hours => proposal_hours)) else proposal_followup_due_at end,\n         accepted_at = case when _dimension = 'proposal' and _to_state = 'accepted' then coalesce(accepted_at, now()) else accepted_at end,\n         deposit_due_at = case when _dimension = 'payment' and _to_state = 'deposit_due' then coalesce(deposit_due_at, now() + make_interval(hours => deposit_hours)) else deposit_due_at end,\n         deposit_paid_at = case when _dimension = 'payment' and _to_state = 'deposit_paid' then coalesce(deposit_paid_at, now()) else deposit_paid_at end,\n         balance_due_at = case when _dimension = 'payment' and _to_state = 'balance_due' then coalesce(balance_due_at, now() + make_interval(hours => balance_hours)) else balance_due_at end,\n         paid_at = case when _dimension = 'payment' and _to_state = 'paid' then coalesce(paid_at, now()) else paid_at end,\n         fulfillment_completed_at = case when _dimension = 'fulfillment' and _to_state = 'completed' then coalesce(fulfillment_completed_at, now()) else fulfillment_completed_at end,\n         lost_at = case when _dimension = 'lifecycle' and _to_state = 'lost' then coalesce(lost_at, now()) else lost_at end,\n         cancelled_at = case when (_dimension = 'lifecycle' and _to_state = 'cancelled') or (_dimension = 'fulfillment' and _to_state = 'cancelled') then coalesce(cancelled_at, now()) else cancelled_at end,\n         metadata = metadata || coalesce(_metadata, '{}'::jsonb),\n         updated_at = now()\n   where id = o.id;\n\n  insert into public.business_opportunity_events\n    (tenant_id, opportunity_id, dimension, from_state, to_state, reason_code, actor_user_id, metadata)\n  values\n    (o.tenant_id, o.id, _dimension, current_state, _to_state, _reason_code, auth.uid(), coalesce(_metadata, '{}'::jsonb));\n\n  if _dimension = 'proposal' and _to_state = 'accepted' and o.lifecycle_state in ('captured','qualified') then\n    update public.business_opportunities set lifecycle_state = 'won', updated_at = now() where id = o.id;\n    insert into public.business_opportunity_events\n      (tenant_id, opportunity_id, dimension, from_state, to_state, reason_code, actor_user_id, metadata)\n    values\n      (o.tenant_id, o.id, 'lifecycle', o.lifecycle_state, 'won', 'proposal_accepted', auth.uid(), '{}'::jsonb);\n  end if;\n\n  select * into final_o from public.business_opportunities where id = o.id;\n  return final_o;\nend;\n$function$\n","identity_arguments":"_opportunity_id uuid, _dimension text, _to_state text, _reason_code text, _metadata jsonb"},{"name":"business_engine_assert_access","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_engine_assert_access(_tenant_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\nbegin\n  if coalesce(auth.role(), '') = 'service_role' then\n    return;\n  end if;\n  if not public.ai_user_in_tenant(_tenant_id) then\n    raise exception 'business_engine_tenant_access_denied' using errcode = '42501';\n  end if;\nend;\n$function$\n","identity_arguments":"_tenant_id uuid"},{"name":"business_engine_attention_trigger","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_engine_attention_trigger()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\nbegin\n  perform public.business_engine_refresh_attention(new.id);\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"business_engine_refresh_attention","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_engine_refresh_attention(_opportunity_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  o public.business_opportunities%rowtype;\n  key_prefix text;\nbegin\n  select * into o from public.business_opportunities where id = _opportunity_id;\n  if not found then\n    raise exception 'business_opportunity_not_found';\n  end if;\n  perform public.business_engine_assert_access(o.tenant_id);\n  key_prefix := o.id::text || ':';\n\n  update public.business_attention_items a\n     set state = 'resolved', resolved_at = now(), updated_at = now()\n   where a.opportunity_id = o.id\n     and a.state in ('open','acknowledged')\n     and (\n       (a.kind = 'opportunity_response_due' and not (o.lifecycle_state = 'captured' and o.response_due_at is not null)) or\n       (a.kind = 'proposal_followup_due' and not (o.proposal_state = 'sent' and o.proposal_followup_due_at is not null)) or\n       (a.kind = 'deposit_due' and not (o.payment_state in ('deposit_due','deposit_overdue'))) or\n       (a.kind = 'scheduling_needed' and not (o.lifecycle_state = 'won' and o.fulfillment_state = 'not_scheduled')) or\n       (a.kind = 'balance_due' and not (o.payment_state in ('balance_due','balance_overdue')))\n     );\n\n  if o.lifecycle_state = 'captured' and o.response_due_at is not null then\n    insert into public.business_attention_items\n      (tenant_id, opportunity_id, kind, priority, deterministic_key, title, summary, due_at, source_state)\n    values\n      (o.tenant_id, o.id, 'opportunity_response_due', 'high', key_prefix || 'opportunity_response_due',\n       'Respond to new opportunity', o.title, o.response_due_at, o.lifecycle_state)\n    on conflict (tenant_id, deterministic_key) do update set\n      title = excluded.title,\n      summary = excluded.summary,\n      due_at = excluded.due_at,\n      source_state = excluded.source_state,\n      state = case when business_attention_items.state = 'resolved' then 'open' else business_attention_items.state end,\n      resolved_at = case when business_attention_items.state = 'resolved' then null else business_attention_items.resolved_at end,\n      updated_at = now();\n  end if;\n\n  if o.proposal_state = 'sent' and o.proposal_followup_due_at is not null then\n    insert into public.business_attention_items\n      (tenant_id, opportunity_id, kind, priority, deterministic_key, title, summary, due_at, source_state)\n    values\n      (o.tenant_id, o.id, 'proposal_followup_due', 'high', key_prefix || 'proposal_followup_due',\n       'Proposal needs follow-up', o.title, o.proposal_followup_due_at, o.proposal_state)\n    on conflict (tenant_id, deterministic_key) do update set\n      title = excluded.title,\n      summary = excluded.summary,\n      due_at = excluded.due_at,\n      source_state = excluded.source_state,\n      state = case when business_attention_items.state = 'resolved' then 'open' else business_attention_items.state end,\n      resolved_at = case when business_attention_items.state = 'resolved' then null else business_attention_items.resolved_at end,\n      updated_at = now();\n  end if;\n\n  if o.payment_state in ('deposit_due','deposit_overdue') then\n    insert into public.business_attention_items\n      (tenant_id, opportunity_id, kind, priority, deterministic_key, title, summary, due_at, source_state)\n    values\n      (o.tenant_id, o.id, 'deposit_due', case when o.payment_state = 'deposit_overdue' then 'urgent' else 'high' end,\n       key_prefix || 'deposit_due', 'Deposit needs attention', o.title, o.deposit_due_at, o.payment_state)\n    on conflict (tenant_id, deterministic_key) do update set\n      priority = excluded.priority,\n      title = excluded.title,\n      summary = excluded.summary,\n      due_at = excluded.due_at,\n      source_state = excluded.source_state,\n      state = case when business_attention_items.state = 'resolved' then 'open' else business_attention_items.state end,\n      resolved_at = case when business_attention_items.state = 'resolved' then null else business_attention_items.resolved_at end,\n      updated_at = now();\n  end if;\n\n  if o.lifecycle_state = 'won' and o.fulfillment_state = 'not_scheduled' then\n    insert into public.business_attention_items\n      (tenant_id, opportunity_id, kind, priority, deterministic_key, title, summary, due_at, source_state)\n    values\n      (o.tenant_id, o.id, 'scheduling_needed', 'high', key_prefix || 'scheduling_needed',\n       'Won opportunity needs scheduling', o.title, o.fulfillment_due_at, o.fulfillment_state)\n    on conflict (tenant_id, deterministic_key) do update set\n      title = excluded.title,\n      summary = excluded.summary,\n      due_at = excluded.due_at,\n      source_state = excluded.source_state,\n      state = case when business_attention_items.state = 'resolved' then 'open' else business_attention_items.state end,\n      resolved_at = case when business_attention_items.state = 'resolved' then null else business_attention_items.resolved_at end,\n      updated_at = now();\n  end if;\n\n  if o.payment_state in ('balance_due','balance_overdue') then\n    insert into public.business_attention_items\n      (tenant_id, opportunity_id, kind, priority, deterministic_key, title, summary, due_at, source_state)\n    values\n      (o.tenant_id, o.id, 'balance_due', case when o.payment_state = 'balance_overdue' then 'urgent' else 'high' end,\n       key_prefix || 'balance_due', 'Outstanding balance needs attention', o.title, o.balance_due_at, o.payment_state)\n    on conflict (tenant_id, deterministic_key) do update set\n      priority = excluded.priority,\n      title = excluded.title,\n      summary = excluded.summary,\n      due_at = excluded.due_at,\n      source_state = excluded.source_state,\n      state = case when business_attention_items.state = 'resolved' then 'open' else business_attention_items.state end,\n      resolved_at = case when business_attention_items.state = 'resolved' then null else business_attention_items.resolved_at end,\n      updated_at = now();\n  end if;\nend;\n$function$\n","identity_arguments":"_opportunity_id uuid"},{"name":"business_engine_touch_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_engine_touch_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nbegin\n  new.updated_at := now();\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"business_intelligence_event_after_insert","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_intelligence_event_after_insert()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\nbegin\n  if lower(new.event_type) in ('opportunity_detected','business_opportunity_detected') then\n    perform public.business_materialize_opportunity_from_intelligence(new.id);\n  end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"business_materialize_opportunity_from_intelligence","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_materialize_opportunity_from_intelligence(_event_id uuid)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  e public.intelligence_events%rowtype;\n  auto_create boolean;\n  min_conf numeric;\n  response_minutes integer;\n  opportunity_id uuid;\n  normalized_dedupe text;\n  normalized_contact uuid;\nbegin\n  select * into e from public.intelligence_events where id = _event_id;\n  if not found then\n    raise exception 'intelligence_event_not_found';\n  end if;\n  perform public.business_engine_assert_access(e.tenant_id);\n\n  if lower(e.event_type) not in ('opportunity_detected','business_opportunity_detected') then\n    return null;\n  end if;\n\n  select p.auto_create_from_intelligence, p.opportunity_auto_create_min_confidence, p.response_due_minutes\n    into auto_create, min_conf, response_minutes\n    from public.business_workflow_policies p\n   where p.tenant_id = e.tenant_id;\n\n  auto_create := coalesce(auto_create, true);\n  min_conf := coalesce(min_conf, 0.8000);\n  response_minutes := coalesce(response_minutes, 60);\n\n  if not auto_create or coalesce(e.confidence_score, 0) < min_conf then\n    return null;\n  end if;\n\n  normalized_dedupe := coalesce(nullif(btrim(e.dedupe_key), ''),\n    concat_ws(':', e.source_module, coalesce(e.source_entity_type, 'event'), coalesce(e.source_entity_id::text, e.id::text)));\n\n  normalized_contact := e.related_contact_id;\n  if normalized_contact is not null and not exists (\n    select 1 from public.unified_contacts c\n     where c.id = normalized_contact and c.tenant_org_id = e.tenant_id::text\n  ) then\n    normalized_contact := null;\n  end if;\n\n  insert into public.business_opportunities (\n    tenant_id, contact_id, source_event_id, source_module, source_entity_type, source_entity_id,\n    dedupe_key, title, summary, confidence_score, lifecycle_state, response_due_at, created_by, metadata\n  ) values (\n    e.tenant_id, normalized_contact, e.id, e.source_module, e.source_entity_type, e.source_entity_id,\n    normalized_dedupe, e.title, e.summary, e.confidence_score, 'captured',\n    coalesce(e.detected_at, now()) + make_interval(mins => response_minutes), auth.uid(),\n    jsonb_build_object(\n      'why_it_matters', e.why_it_matters,\n      'recommended_action', e.recommended_action,\n      'evidence', e.evidence_json,\n      'normalized_from', 'intelligence_events'\n    )\n  )\n  on conflict (tenant_id, dedupe_key) do update set\n    contact_id = coalesce(business_opportunities.contact_id, excluded.contact_id),\n    source_event_id = excluded.source_event_id,\n    source_module = excluded.source_module,\n    source_entity_type = coalesce(excluded.source_entity_type, business_opportunities.source_entity_type),\n    source_entity_id = coalesce(excluded.source_entity_id, business_opportunities.source_entity_id),\n    summary = coalesce(excluded.summary, business_opportunities.summary),\n    confidence_score = greatest(coalesce(business_opportunities.confidence_score, 0), coalesce(excluded.confidence_score, 0)),\n    metadata = business_opportunities.metadata || excluded.metadata,\n    updated_at = now()\n  returning id into opportunity_id;\n\n  insert into public.business_opportunity_events (\n    tenant_id, opportunity_id, dimension, from_state, to_state, reason_code, actor_user_id, source_event_id, metadata\n  ) values (\n    e.tenant_id, opportunity_id, 'materialization', null, 'captured', 'intelligence_event_materialized',\n    auth.uid(), e.id, jsonb_build_object('dedupe_key', normalized_dedupe, 'confidence_score', e.confidence_score)\n  );\n\n  perform public.business_engine_refresh_attention(opportunity_id);\n  return opportunity_id;\nend;\n$function$\n","identity_arguments":"_event_id uuid"},{"name":"business_now_label","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_now_label()\n RETURNS text\n LANGUAGE sql\n STABLE\n SET search_path TO 'pg_catalog', 'public'\nRETURN to_business_time_label(now())\n","identity_arguments":""},{"name":"business_set_attention_state","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_set_attention_state(_attention_id uuid, _state text)\n RETURNS business_attention_items\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  a public.business_attention_items%rowtype;\n  final_a public.business_attention_items%rowtype;\nbegin\n  select * into a from public.business_attention_items where id = _attention_id for update;\n  if not found then raise exception 'business_attention_item_not_found'; end if;\n  perform public.business_engine_assert_access(a.tenant_id);\n  if _state not in ('open','acknowledged','resolved','dismissed') then\n    raise exception 'business_attention_state_invalid:%', _state;\n  end if;\n\n  update public.business_attention_items\n     set state = _state,\n         acknowledged_at = case when _state = 'acknowledged' then now() when _state = 'open' then null else acknowledged_at end,\n         resolved_at = case when _state = 'resolved' then now() when _state = 'open' then null else resolved_at end,\n         dismissed_at = case when _state = 'dismissed' then now() when _state = 'open' then null else dismissed_at end,\n         updated_at = now()\n   where id = a.id;\n  select * into final_a from public.business_attention_items where id = a.id;\n  return final_a;\nend;\n$function$\n","identity_arguments":"_attention_id uuid, _state text"},{"name":"business_timezone","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_timezone()\n RETURNS text\n LANGUAGE sql\n STABLE\n SET search_path TO 'pg_catalog', 'public'\nRETURN 'America/New_York'::text\n","identity_arguments":""},{"name":"business_timezone_label","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_timezone_label()\n RETURNS text\n LANGUAGE sql\n STABLE\n SET search_path TO 'pg_catalog', 'public'\nRETURN 'ET'::text\n","identity_arguments":""},{"name":"business_update_opportunity_terms","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.business_update_opportunity_terms(_opportunity_id uuid, _patch jsonb)\n RETURNS business_opportunities\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  o public.business_opportunities%rowtype;\n  final_o public.business_opportunities%rowtype;\n  allowed_keys constant text[] := array[\n    'contact_id','title','summary','category','estimated_value','quoted_amount','deposit_amount','balance_amount',\n    'response_due_at','proposal_followup_due_at','deposit_due_at','fulfillment_due_at','balance_due_at',\n    'event_booking_id','invoice_id','calendar_event_id','metadata'\n  ];\n  unknown_keys text[];\n  linked_id uuid;\nbegin\n  if _patch is null or jsonb_typeof(_patch) <> 'object' then\n    raise exception 'business_terms_patch_object_required';\n  end if;\n\n  select * into o from public.business_opportunities where id = _opportunity_id for update;\n  if not found then raise exception 'business_opportunity_not_found'; end if;\n  perform public.business_engine_assert_access(o.tenant_id);\n\n  select array_agg(k) into unknown_keys\n    from jsonb_object_keys(_patch) as k\n   where not (k = any(allowed_keys));\n  if coalesce(cardinality(unknown_keys), 0) > 0 then\n    raise exception 'business_terms_patch_unknown_keys:%', array_to_string(unknown_keys, ',');\n  end if;\n\n  if _patch ? 'title' and nullif(btrim(coalesce(_patch->>'title','')), '') is null then\n    raise exception 'business_opportunity_title_required';\n  end if;\n  if _patch ? 'metadata' and jsonb_typeof(_patch->'metadata') not in ('object','null') then\n    raise exception 'business_terms_metadata_object_required';\n  end if;\n\n  if _patch ? 'contact_id' and jsonb_typeof(_patch->'contact_id') <> 'null' then\n    linked_id := (_patch->>'contact_id')::uuid;\n    if not exists (select 1 from public.unified_contacts c where c.id = linked_id and c.tenant_org_id = o.tenant_id::text) then\n      raise exception 'business_terms_contact_tenant_mismatch';\n    end if;\n  end if;\n\n  if _patch ? 'event_booking_id' and jsonb_typeof(_patch->'event_booking_id') <> 'null' then\n    linked_id := (_patch->>'event_booking_id')::uuid;\n    if not exists (select 1 from public.event_bookings b where b.id = linked_id and b.tenant_org_id = o.tenant_id::text) then\n      raise exception 'business_terms_event_booking_tenant_mismatch';\n    end if;\n  end if;\n\n  if _patch ? 'invoice_id' and jsonb_typeof(_patch->'invoice_id') <> 'null' then\n    linked_id := (_patch->>'invoice_id')::uuid;\n    if not exists (select 1 from public.invoices i where i.id = linked_id and i.tenant_org_id = o.tenant_id::text) then\n      raise exception 'business_terms_invoice_tenant_mismatch';\n    end if;\n  end if;\n\n  if _patch ? 'calendar_event_id' and jsonb_typeof(_patch->'calendar_event_id') <> 'null' then\n    linked_id := (_patch->>'calendar_event_id')::uuid;\n    if not exists (select 1 from public.user_calendar_events c where c.id = linked_id and c.tenant_org_id = o.tenant_id::text) then\n      raise exception 'business_terms_calendar_event_tenant_mismatch';\n    end if;\n  end if;\n\n  update public.business_opportunities\n     set contact_id = case when _patch ? 'contact_id' then (_patch->>'contact_id')::uuid else contact_id end,\n         title = case when _patch ? 'title' then btrim(_patch->>'title') else title end,\n         summary = case when _patch ? 'summary' then _patch->>'summary' else summary end,\n         category = case when _patch ? 'category' then _patch->>'category' else category end,\n         estimated_value = case when _patch ? 'estimated_value' then (_patch->>'estimated_value')::numeric else estimated_value end,\n         quoted_amount = case when _patch ? 'quoted_amount' then (_patch->>'quoted_amount')::numeric else quoted_amount end,\n         deposit_amount = case when _patch ? 'deposit_amount' then (_patch->>'deposit_amount')::numeric else deposit_amount end,\n         balance_amount = case when _patch ? 'balance_amount' then (_patch->>'balance_amount')::numeric else balance_amount end,\n         response_due_at = case when _patch ? 'response_due_at' then (_patch->>'response_due_at')::timestamptz else response_due_at end,\n         proposal_followup_due_at = case when _patch ? 'proposal_followup_due_at' then (_patch->>'proposal_followup_due_at')::timestamptz else proposal_followup_due_at end,\n         deposit_due_at = case when _patch ? 'deposit_due_at' then (_patch->>'deposit_due_at')::timestamptz else deposit_due_at end,\n         fulfillment_due_at = case when _patch ? 'fulfillment_due_at' then (_patch->>'fulfillment_due_at')::timestamptz else fulfillment_due_at end,\n         balance_due_at = case when _patch ? 'balance_due_at' then (_patch->>'balance_due_at')::timestamptz else balance_due_at end,\n         event_booking_id = case when _patch ? 'event_booking_id' then (_patch->>'event_booking_id')::uuid else event_booking_id end,\n         invoice_id = case when _patch ? 'invoice_id' then (_patch->>'invoice_id')::uuid else invoice_id end,\n         calendar_event_id = case when _patch ? 'calendar_event_id' then (_patch->>'calendar_event_id')::uuid else calendar_event_id end,\n         metadata = case when _patch ? 'metadata' and jsonb_typeof(_patch->'metadata') = 'object' then metadata || (_patch->'metadata') else metadata end,\n         updated_at = now()\n   where id = o.id;\n\n  insert into public.business_opportunity_events\n    (tenant_id, opportunity_id, dimension, from_state, to_state, reason_code, actor_user_id, metadata)\n  values\n    (o.tenant_id, o.id, 'terms', null, null, 'terms_updated', auth.uid(), _patch);\n\n  select * into final_o from public.business_opportunities where id = o.id;\n  return final_o;\nend;\n$function$\n","identity_arguments":"_opportunity_id uuid, _patch jsonb"},{"name":"calculate_quality_score","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.calculate_quality_score(p_name text, p_phone text, p_email text, p_address text, p_city text, p_state text, p_zip text)\n RETURNS integer\n LANGUAGE plpgsql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_score INTEGER := 0;\nBEGIN\n  IF p_name IS NOT NULL AND LENGTH(TRIM(p_name)) > 2 THEN v_score := v_score + 15; END IF;\n  IF p_phone IS NOT NULL AND LENGTH(REGEXP_REPLACE(p_phone, '[^0-9]', '', 'g')) >= 10 THEN v_score := v_score + 25; END IF;\n  IF p_email IS NOT NULL AND p_email ~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}$' THEN v_score := v_score + 15; END IF;\n  IF p_address IS NOT NULL AND LENGTH(TRIM(p_address)) > 5 AND NOT (TRIM(p_address) ~ '^[A-Z]{2}$') THEN v_score := v_score + 20; END IF;\n  IF p_city IS NOT NULL AND LENGTH(TRIM(p_city)) > 2 AND NOT (TRIM(p_city) ~ '^[A-Z]{2}$') THEN v_score := v_score + 15; END IF;\n  IF p_zip IS NOT NULL AND LENGTH(REGEXP_REPLACE(p_zip, '[^0-9]', '', 'g')) >= 5 THEN v_score := v_score + 10; END IF;\n  RETURN v_score;\nEND;\n$function$\n","identity_arguments":"p_name text, p_phone text, p_email text, p_address text, p_city text, p_state text, p_zip text"},{"name":"can_contact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.can_contact(p_tenant_id uuid, p_contact_id uuid, p_channel text)\n RETURNS boolean\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_prefs record;\n  v_unsubscribed boolean;\n  v_uid uuid := auth.uid();\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       v_uid IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(v_uid), false)\n         AND NOT coalesce(public.is_tenant_member(v_uid, p_tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'contact compliance access denied' USING ERRCODE = '42501';\n  END IF;\n\n  IF p_channel = 'email' THEN\n    SELECT EXISTS(\n      SELECT 1 FROM public.email_unsubscribes\n      WHERE tenant_id = p_tenant_id\n        AND contact_id = p_contact_id\n        AND resubscribed_at IS NULL\n    ) INTO v_unsubscribed;\n    IF v_unsubscribed THEN RETURN false; END IF;\n  END IF;\n\n  SELECT * INTO v_prefs\n  FROM public.contact_communication_preferences\n  WHERE tenant_id = p_tenant_id AND contact_id = p_contact_id;\n\n  IF NOT FOUND THEN RETURN true; END IF;\n  IF v_prefs.do_not_contact_until IS NOT NULL AND v_prefs.do_not_contact_until > now() THEN\n    RETURN false;\n  END IF;\n\n  CASE p_channel\n    WHEN 'email' THEN RETURN coalesce(v_prefs.email_enabled, true);\n    WHEN 'sms' THEN RETURN coalesce(v_prefs.sms_enabled, true);\n    WHEN 'call' THEN RETURN coalesce(v_prefs.call_enabled, true);\n    ELSE RETURN true;\n  END CASE;\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_contact_id uuid, p_channel text"},{"name":"can_manage_experience_studio","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.can_manage_experience_studio()\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$ SELECT public.is_system_admin(auth.uid()); $function$\n","identity_arguments":""},{"name":"can_manage_page_override","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.can_manage_page_override(_user_id uuid, _tenant_scope text)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare _tenant_id uuid;\nbegin\n  if _user_id is null or _tenant_scope is null then return false; end if;\n  if public.is_platform_admin(_user_id) then return true; end if;\n  begin _tenant_id := _tenant_scope::uuid;\n  exception when invalid_text_representation then return false;\n  end;\n  return public.is_tenant_owner_or_admin(_user_id, _tenant_id);\nend;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_scope text"},{"name":"can_view_tenant_member_academy","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.can_view_tenant_member_academy(_viewer uuid, _target uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT\n    _viewer = _target\n    OR public.is_system_admin(_viewer)\n    OR EXISTS (\n      SELECT 1\n      FROM public.user_tenant_memberships m_target\n      JOIN public.user_tenant_memberships m_viewer\n        ON m_viewer.tenant_id = m_target.tenant_id\n       AND m_viewer.user_id = _viewer\n       AND m_viewer.status = 'active'\n      WHERE m_target.user_id = _target\n        AND m_target.status = 'active'\n        AND (\n          m_viewer.is_owner = true\n          OR public.is_tenant_owner(_viewer, m_target.tenant_id)\n          OR EXISTS (\n            SELECT 1 FROM public.user_roles ur\n            WHERE ur.user_id = _viewer\n              AND ur.tenant_id = m_target.tenant_id\n              AND ur.role IN ('Owner'::app_role, 'Admin'::app_role, 'Tenant Owner'::app_role)\n          )\n        )\n    );\n$function$\n","identity_arguments":"_viewer uuid, _target uuid"},{"name":"canonical_tenant_type","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.canonical_tenant_type(p_value text)\n RETURNS text\n LANGUAGE plpgsql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_token text := trim(both '_' from regexp_replace(upper(trim(coalesce(p_value, ''))), '[^A-Z0-9]+', '_', 'g'));\nBEGIN\n  IF v_token = '' THEN\n    RETURN NULL;\n  END IF;\n\n  RETURN CASE\n    WHEN v_token IN ('MITIGATION','EMERGENCY_MITIGATION','RESTORATION','WATER_MITIGATION','TARPING','SCETARPING','SCE_TARPING') THEN 'MITIGATION'\n    WHEN v_token IN ('ROOFING','ROOFER','ROOFING_COMPANY','ROOFINGCOMPANY') THEN 'ROOFING_COMPANY'\n    WHEN v_token IN ('PUBLIC_ADJUSTER','PUBLIC_ADJUSTER_FIRM','PUBLICADJUSTERFIRM','PA') THEN 'PUBLIC_ADJUSTER_FIRM'\n    WHEN v_token IN ('REALTOR','REAL_ESTATE','REAL_ESTATE_AGENT','BROKERAGE') THEN 'REALTOR'\n    WHEN v_token IN ('LAWN_CARE','LAWNCARE','LAWN','LANDSCAPING','ROUTE_BASED','ROUTE_BASED_SERVICE','FIELD_SERVICE') THEN 'LAWN_CARE'\n    WHEN v_token IN ('TIRE_SHOP','TIRESHOP','TIRE_STORE','TIRE_AND_AUTO','TIRE_AUTO') THEN 'TIRE_SHOP'\n    WHEN v_token IN ('AUTO_DETAILING','AUTODETAILING','AUTO_DETAILER','MOBILE_DETAILING','CAR_DETAILING','DETAILING') THEN 'AUTO_DETAILING'\n    WHEN v_token IN ('CAFE_QSR','CAFE','QSR','QUICK_SERVICE','QUICK_SERVICE_RESTAURANT','FOOD_BEVERAGE','FOOD_AND_BEVERAGE','RESTAURANT') THEN 'CAFE_QSR'\n    WHEN v_token IN ('MOBILE_VENDOR','MOBILEVENDOR','FOOD_TRUCK','FOODTRUCK','MOBILE_KITCHEN','MOBILEKITCHEN','POP_UP_VENDOR') THEN 'MOBILE_VENDOR'\n    WHEN v_token IN ('SHORT_TERM_RENTAL','SHORT_TERM_RENTALS','VACATION_RENTAL','VACATION_RENTALS','STR') THEN 'SHORT_TERM_RENTAL'\n    WHEN v_token IN ('MISC','MISCELLANEOUS','FACILITY','FACILITY_SERVICES','RECORDS','SPECIAL','HOSPITALITY','FOOD_SERVICE') THEN 'MISC'\n    ELSE NULL\n  END;\nEND;\n$function$\n","identity_arguments":"p_value text"},{"name":"cc_scrub_text","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.cc_scrub_text(t text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT CASE\n    WHEN t IS NULL THEN NULL\n    ELSE regexp_replace(\n      t,\n      '(\\+?\\d[\\d\\s().-]{8,}\\d)',\n      '[redacted-phone]',\n      'g'\n    )\n  END\n$function$\n","identity_arguments":"t text"},{"name":"cce_apply_approval_gate","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.cce_apply_approval_gate()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF TG_OP = 'INSERT' THEN\n    IF NEW.requires_approval = false AND public.command_event_requires_approval(NEW.event_type) THEN\n      NEW.requires_approval := true;\n    END IF;\n    IF NEW.requires_approval = true THEN\n      NEW.status := 'pending_approval';\n      NEW.approval_status := 'pending';\n    END IF;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"cce_dispatch_owner_alert","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.cce_dispatch_owner_alert()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_should_fire boolean := false;\n  v_supabase_url text := 'https://ymntrajfubicyxwwdxxa.supabase.co';\n  v_service_key text;\n  v_event_type text;\n  v_headers jsonb;\nBEGIN\n  -- cc-agent/report invokes cc-notify-owner directly after create/dedupe.\n  -- This trigger is a fallback for system/direct DB event creation only.\n  IF NEW.actor_type = 'agent' THEN\n    RETURN NEW;\n  END IF;\n\n  v_event_type := lower(coalesce(NEW.event_type, ''));\n\n  IF lower(coalesce(NEW.priority, '')) IN ('urgent','blocker') THEN\n    v_should_fire := true;\n  ELSIF NEW.requires_approval = true OR NEW.approval_status = 'pending' THEN\n    v_should_fire := true;\n  ELSIF v_event_type LIKE '%deploy%' THEN\n    v_should_fire := true;\n  END IF;\n\n  IF TG_OP = 'UPDATE' THEN\n    IF (lower(coalesce(OLD.priority,'')) IN ('urgent','blocker'))\n       OR OLD.requires_approval = true\n       OR OLD.approval_status = 'pending'\n       OR lower(coalesce(OLD.event_type,'')) LIKE '%deploy%' THEN\n      RETURN NEW;\n    END IF;\n  END IF;\n\n  IF NOT v_should_fire THEN\n    RETURN NEW;\n  END IF;\n\n  BEGIN\n    SELECT decrypted_secret INTO v_service_key\n    FROM vault.decrypted_secrets WHERE name = 'SUPABASE_SERVICE_ROLE_KEY' LIMIT 1;\n  EXCEPTION WHEN OTHERS THEN\n    NULL;\n  END;\n\n  v_headers := jsonb_build_object('Content-Type','application/json');\n  IF v_service_key IS NOT NULL THEN\n    v_headers := v_headers || jsonb_build_object(\n      'Authorization','Bearer ' || v_service_key,\n      'apikey', v_service_key\n    );\n  END IF;\n\n  PERFORM net.http_post(\n    url := v_supabase_url || '/functions/v1/cc-notify-owner',\n    headers := v_headers,\n    body := jsonb_build_object('event_id', NEW.id)\n  );\n\n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  INSERT INTO public.command_center_activity_log (\n    tenant_id,\n    command_center_event_id,\n    actor_user_id,\n    actor_role,\n    actor_type,\n    actor_display_name,\n    action_type,\n    new_value,\n    notes\n  ) VALUES (\n    NEW.tenant_id,\n    NEW.id,\n    NULL,\n    'system:cce_dispatch_owner_alert',\n    'system',\n    'Command Center Owner Alert Trigger',\n    'owner_notify_failed',\n    'trigger_exception',\n    'Database trigger failed before invoking cc-notify-owner: ' || SQLERRM\n  );\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"cce_on_insert","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.cce_on_insert()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nBEGIN\n  INSERT INTO public.command_center_activity_log\n    (tenant_id, command_center_event_id, actor_user_id, actor_role, action_type, new_value, notes)\n  VALUES (NEW.tenant_id, NEW.id, NEW.created_by_user_id, NEW.created_by_role, 'created', NEW.status, NEW.title);\n\n  IF coalesce(NEW.mission_context->>'silent', 'false') <> 'true' THEN\n    INSERT INTO public.notifications (user_id, tenant_id, type, title, message, link, metadata)\n    SELECT DISTINCT ur.user_id, NEW.tenant_id::text, 'command_center',\n           CASE WHEN NEW.priority IN ('urgent','blocker') THEN '🚨 ' ELSE '' END || NEW.title,\n           COALESCE(LEFT(NEW.message, 200), ''),\n           '/command-center/' || NEW.id::text,\n           jsonb_build_object('event_id', NEW.id, 'priority', NEW.priority,\n                              'source_module', NEW.source_module, 'created_by_role', NEW.created_by_role)\n    FROM public.user_roles ur\n    LEFT JOIN public.user_tenant_memberships m\n      ON m.user_id=ur.user_id AND m.tenant_id=ur.tenant_id\n    WHERE ur.user_id <> NEW.created_by_user_id\n      AND (\n        public.is_system_admin(ur.user_id)\n        OR (\n          ur.tenant_id = NEW.tenant_id\n          AND m.status='active'\n          AND ur.role::text IN ('GodMode','Admin','Owner','Tenant Owner','Manager','command_agent')\n        )\n      );\n  END IF;\n  RETURN NEW;\nEND\n$function$\n","identity_arguments":""},{"name":"cce_on_update","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.cce_on_update()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nDECLARE\n  _actor uuid := auth.uid();\n  _role text;\nBEGIN\n  IF _actor IS NOT NULL AND public.is_system_admin(_actor) THEN\n    _role := 'PlatformAdmin';\n  ELSE\n    SELECT ur.role::text INTO _role\n    FROM public.user_tenant_memberships m\n    JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_actor\n      AND m.tenant_id=NEW.tenant_id\n      AND m.status='active'\n    LIMIT 1;\n  END IF;\n\n  IF NEW.status IS DISTINCT FROM OLD.status THEN\n    INSERT INTO public.command_center_activity_log\n      (tenant_id, command_center_event_id, actor_user_id, actor_role, action_type, old_value, new_value)\n    VALUES (NEW.tenant_id, NEW.id, _actor, _role,\n      CASE NEW.status WHEN 'acknowledged' THEN 'acknowledged' WHEN 'resolved' THEN 'resolved'\n                      WHEN 'closed' THEN 'closed' ELSE 'status_changed' END,\n      OLD.status, NEW.status);\n  END IF;\n\n  IF NEW.assigned_to_user_id IS DISTINCT FROM OLD.assigned_to_user_id THEN\n    INSERT INTO public.command_center_activity_log\n      (tenant_id, command_center_event_id, actor_user_id, actor_role, action_type, old_value, new_value)\n    VALUES (NEW.tenant_id, NEW.id, _actor, _role, 'assigned',\n            OLD.assigned_to_user_id::text, NEW.assigned_to_user_id::text);\n  END IF;\n  RETURN NEW;\nEND\n$function$\n","identity_arguments":""},{"name":"ccm_on_insert","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ccm_on_insert()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  INSERT INTO public.command_center_activity_log (tenant_id, command_center_event_id, actor_user_id, actor_role, action_type, notes)\n  VALUES (NEW.tenant_id, NEW.command_center_event_id, NEW.sender_user_id, NEW.sender_role, 'replied', LEFT(NEW.message, 200));\n  RETURN NEW;\nEND $function$\n","identity_arguments":""},{"name":"check_account_lockout","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.check_account_lockout(p_email text)\n RETURNS TABLE(is_locked boolean, unlock_at timestamp with time zone, attempts_count integer)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE v_failed_count INT; v_last_attempt TIMESTAMPTZ;\nBEGIN\n  SELECT COUNT(*)::INT, MAX(created_at) INTO v_failed_count, v_last_attempt\n  FROM login_attempts WHERE email = lower(p_email) AND success = false AND created_at > now() - interval '15 minutes';\n  IF v_failed_count >= 5 THEN RETURN QUERY SELECT true, v_last_attempt + interval '15 minutes', v_failed_count;\n  ELSE RETURN QUERY SELECT false, NULL::TIMESTAMPTZ, v_failed_count; END IF;\nEND; $function$\n","identity_arguments":"p_email text"},{"name":"check_frequency_cap","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.check_frequency_cap(p_tenant_id text, p_phone_normalized text, p_window_days integer DEFAULT 30, p_max_attempts integer DEFAULT 3)\n RETURNS TABLE(allowed boolean, attempts_in_window integer, next_allowed_at timestamp with time zone)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_count int;\n  v_oldest timestamptz;\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(p_tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'frequency cap access denied' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT count(*), min(created_at)\n    INTO v_count, v_oldest\n  FROM public.call_attempts_log\n  WHERE tenant_org_id = p_tenant_id\n    AND phone_normalized = p_phone_normalized\n    AND was_inbound = false\n    AND created_at > now() - (p_window_days || ' days')::interval;\n\n  IF v_count < p_max_attempts THEN\n    RETURN QUERY SELECT true, v_count, NULL::timestamptz;\n  ELSE\n    RETURN QUERY SELECT false, v_count, v_oldest + (p_window_days || ' days')::interval;\n  END IF;\nEND;\n$function$\n","identity_arguments":"p_tenant_id text, p_phone_normalized text, p_window_days integer, p_max_attempts integer"},{"name":"claim_auto_unlock_upload_tickets","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.claim_auto_unlock_upload_tickets(p_ip_hash text, p_paths text[])\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_catalog', 'pg_temp'\nAS $function$\nDECLARE\n  v_expected integer;\n  v_claimed integer;\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role' THEN\n    RAISE EXCEPTION 'service role required' USING ERRCODE='42501';\n  END IF;\n  v_expected := cardinality(p_paths);\n  IF p_ip_hash !~ '^[0-9a-f]{64}$' OR v_expected IS NULL OR v_expected < 1 OR v_expected > 2 THEN\n    RAISE EXCEPTION 'upload_ticket_invalid' USING ERRCODE='22023';\n  END IF;\n  UPDATE public.auto_unlock_upload_tickets\n     SET consumed_at=now()\n   WHERE ip_hash=p_ip_hash\n     AND object_path=ANY(p_paths)\n     AND consumed_at IS NULL\n     AND expires_at > now();\n  GET DIAGNOSTICS v_claimed = ROW_COUNT;\n  IF v_claimed <> v_expected THEN\n    RAISE EXCEPTION 'upload_ticket_invalid' USING ERRCODE='P0001';\n  END IF;\n  RETURN v_claimed;\nEND;\n$function$\n","identity_arguments":"p_ip_hash text, p_paths text[]"},{"name":"claim_due_pending_voicemail_drops","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.claim_due_pending_voicemail_drops(_limit integer DEFAULT 50)\n RETURNS TABLE(id uuid, tenant_id uuid, rep_id uuid, voicemail_template_id uuid, active_call_session_id uuid, homeowner_call_sid text, slot_requested smallint, rep_release_requested boolean)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  RETURN QUERY\n  WITH due AS (\n    SELECT pvd.id\n    FROM public.pending_voicemail_drops pvd\n    WHERE pvd.status = 'armed'\n      AND pvd.fire_at <= now()\n      AND pvd.playback_started_at IS NULL\n    ORDER BY pvd.fire_at ASC\n    LIMIT _limit\n    FOR UPDATE SKIP LOCKED\n  )\n  UPDATE public.pending_voicemail_drops pvd\n  SET status = 'playback_started',\n      playback_started_at = now(),\n      timing_mode = COALESCE(pvd.timing_mode, 'fallback_delay')\n  FROM due\n  WHERE pvd.id = due.id\n  RETURNING\n    pvd.id,\n    pvd.tenant_id,\n    pvd.rep_id,\n    pvd.voicemail_template_id,\n    pvd.active_call_session_id,\n    pvd.homeowner_call_sid,\n    pvd.slot_requested,\n    pvd.rep_release_requested;\nEND;\n$function$\n","identity_arguments":"_limit integer"},{"name":"claim_next_command_center_mission","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.claim_next_command_center_mission(_worker text, _lease_seconds integer DEFAULT 90)\n RETURNS SETOF command_center_events\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  RETURN QUERY\n  WITH candidate AS (\n    SELECT id\n    FROM public.command_center_events\n    WHERE mission_status IN ('accepted','queued','pending','running','waiting','retryable')\n      AND owner_authorized = true\n      AND coalesce(mission_context->>'supervisor_owner', '') <> 'cc-execution'\n      AND (lease_expires_at IS NULL OR lease_expires_at < now())\n    ORDER BY priority DESC, created_at\n    FOR UPDATE SKIP LOCKED\n    LIMIT 1\n  )\n  UPDATE public.command_center_events e\n  SET leased_by = _worker,\n      lease_expires_at = now() + make_interval(secs => greatest(30, least(_lease_seconds, 300))),\n      mission_status = 'running',\n      mission_phase = coalesce(e.mission_phase, 'preflight'),\n      started_at = coalesce(e.started_at, now()),\n      last_progress_at = now(),\n      attempt_count = e.attempt_count + 1\n  FROM candidate\n  WHERE e.id = candidate.id\n  RETURNING e.*;\nEND;\n$function$\n","identity_arguments":"_worker text, _lease_seconds integer"},{"name":"claim_payment_label","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.claim_payment_label(_status claim_payment_lifecycle)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT CASE _status\n    WHEN 'not_started' THEN 'Not started'\n    WHEN 'claim_info_needed' THEN 'Claim info needed'\n    WHEN 'ready_to_invoice' THEN 'Ready to invoice'\n    WHEN 'invoice_sent' THEN 'Invoice sent'\n    WHEN 'submitted_to_carrier' THEN 'Submitted to carrier'\n    WHEN 'payment_pending' THEN 'Payment pending'\n    WHEN 'check_sent_to_carrier' THEN 'Check sent to carrier'\n    WHEN 'check_sent_direct_to_homeowner' THEN 'Check sent direct to Homeowner'\n    WHEN 'paid' THEN 'Paid'\n    WHEN 'denied' THEN 'Denied'\n    WHEN 'follow_up_needed' THEN 'Follow-up needed'\n  END\n$function$\n","identity_arguments":"_status claim_payment_lifecycle"},{"name":"classify_lead_origin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.classify_lead_origin(_source text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT CASE\n    WHEN _source IS NULL OR _source = '' THEN 'system'\n    WHEN lower(_source) IN (\n      'door canvassing', 'door_canvassing', 'canvassing',\n      'rep_added', 'rep added',\n      'referral',\n      'customer_added', 'customer added',\n      'manual create', 'manual_create', 'manual',\n      'document scan', 'document_scan', 'doc scan'\n    ) THEN 'personal'\n    WHEN lower(_source) IN (\n      'import', 'csv', 'csv_import', 'manual csv upload',\n      'mojo leadstore', 'mojo_leadstore', 'mojo',\n      'skip tracer', 'skip_tracer', 'skiptrace',\n      'batch scanner', 'batch_scanner', 'batch upload',\n      'space coast transfer', 'space_coast_transfer',\n      'integration', 'api'\n    ) THEN 'system'\n    ELSE 'system'\n  END\n$function$\n","identity_arguments":"_source text"},{"name":"clone_onboarding_templates_internal","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.clone_onboarding_templates_internal(p_tenant_id uuid, p_canonical_type text, p_track text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_stages int := 0;\n  v_scripts int := 0;\n  v_dialogues int := 0;\nbegin\n  insert into public.pipeline_stages(\n    tenant_org_id,tenancy_type,pipeline_kind,name,color,order_index,is_active,is_closed,is_won,is_template\n  )\n  select p_tenant_id::text,p_canonical_type,pipeline_kind,name,color,order_index,is_active,is_closed,is_won,false\n  from public.pipeline_stages\n  where is_template=true and tenant_org_id is null\n    and lower(tenancy_type) in (lower(p_canonical_type),lower(p_track))\n  on conflict do nothing;\n  get diagnostics v_stages=row_count;\n\n  insert into public.call_scripts(\n    tenant_org_id,tenancy_type,script_name,script_type,script_content,prompts,is_template,is_active,order_index\n  )\n  select p_tenant_id::text,p_canonical_type,script_name,script_type,script_content,prompts,false,is_active,order_index\n  from public.call_scripts\n  where is_template=true and tenant_org_id is null\n    and lower(tenancy_type) in (lower(p_canonical_type),lower(p_track))\n  on conflict do nothing;\n  get diagnostics v_scripts=row_count;\n\n  insert into public.workflow_dialogue_stages(\n    tenant_org_id,tenancy_type,workflow_id,stage_name,stage_order,script_text,prompts,is_active,is_template\n  )\n  select p_tenant_id::text,p_canonical_type,workflow_id,stage_name,stage_order,script_text,prompts,is_active,false\n  from public.workflow_dialogue_stages\n  where is_template=true and tenant_org_id is null\n    and lower(tenancy_type) in (lower(p_canonical_type),lower(p_track))\n  on conflict do nothing;\n  get diagnostics v_dialogues=row_count;\n\n  return jsonb_build_object('ok',true,'stages',v_stages,'scripts',v_scripts,'dialogues',v_dialogues);\nend;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_canonical_type text, p_track text"},{"name":"command_center_normalize_tenant_ref","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.command_center_normalize_tenant_ref(_value text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE PARALLEL SAFE\n SET search_path TO ''\nAS $function$\n select btrim(regexp_replace(regexp_replace(lower(coalesce(_value,'')), '[^a-z0-9]+',' ','g'),'\\s+',' ','g'));\n$function$\n","identity_arguments":"_value text"},{"name":"command_center_tenant_acronym","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.command_center_tenant_acronym(_value text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE PARALLEL SAFE\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\n with words as (\n  select token, ord from regexp_split_to_table(public.command_center_normalize_tenant_ref(_value),'\\s+') with ordinality as w(token,ord)\n  where token<>'' and token not in ('the','and','of','a','an','inc','llc','ltd','corp','corporation','company','co')\n ) select coalesce(string_agg(left(token,1),'' order by ord),'') from words;\n$function$\n","identity_arguments":"_value text"},{"name":"command_event_requires_approval","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.command_event_requires_approval(_event_type text)\n RETURNS boolean\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT _event_type = ANY (ARRAY[\n    'comms_drafted',\n    'code_change_proposed',\n    'outbound_customer_message',\n    'code_repo_pr_action',\n    'role_permission_change',\n    'rls_change',\n    'tenant_security_change',\n    'billing_change',\n    'compliance_change',\n    'job_approval',\n    'payment_status_change',\n    'claim_status_change'\n  ]);\n$function$\n","identity_arguments":"_event_type text"},{"name":"comprehensive_audit_trigger_fn","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.comprehensive_audit_trigger_fn()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user_id UUID;\n  v_tenant_id UUID;\n  v_resource_id TEXT;\n  v_old_data JSONB;\n  v_new_data JSONB;\n  v_changed JSONB := '{}'::JSONB;\n  v_old_changed JSONB := '{}'::JSONB;\n  v_new_changed JSONB := '{}'::JSONB;\n  v_key TEXT;\n  v_user_name TEXT;\n  v_user_email TEXT;\n  v_resource_name TEXT;\n  v_tenant_name TEXT;\n  v_summary TEXT;\n  v_change_parts TEXT[] := '{}';\n  v_skip_fields TEXT[] := ARRAY['updated_at','created_at','last_touched_at','recency_score','engagement_score','quality_score','property_data_fetched_at','normalized_address','normalized_email','normalized_phone','geocoded_at','geocode_confidence'];\nBEGIN\n  BEGIN\n    v_user_id := auth.uid();\n  EXCEPTION WHEN OTHERS THEN\n    v_user_id := NULL;\n  END;\n\n  IF TG_OP = 'DELETE' THEN\n    v_old_data := to_jsonb(OLD);\n    v_new_data := NULL;\n    v_resource_id := OLD.id::TEXT;\n  ELSIF TG_OP = 'INSERT' THEN\n    v_old_data := NULL;\n    v_new_data := to_jsonb(NEW);\n    v_resource_id := NEW.id::TEXT;\n  ELSE\n    v_old_data := to_jsonb(OLD);\n    v_new_data := to_jsonb(NEW);\n    v_resource_id := NEW.id::TEXT;\n  END IF;\n\n  BEGIN\n    IF TG_OP = 'DELETE' THEN\n      v_tenant_id := COALESCE((v_old_data->>'tenant_org_id')::UUID, (v_old_data->>'tenant_id')::UUID);\n    ELSE\n      v_tenant_id := COALESCE((v_new_data->>'tenant_org_id')::UUID, (v_new_data->>'tenant_id')::UUID);\n    END IF;\n  EXCEPTION WHEN OTHERS THEN\n    v_tenant_id := NULL;\n  END;\n\n  IF v_user_id IS NOT NULL THEN\n    SELECT p.name, p.email INTO v_user_name, v_user_email\n    FROM profiles p WHERE p.id = v_user_id;\n  END IF;\n\n  IF TG_TABLE_NAME = 'unified_contacts' THEN\n    IF TG_OP = 'DELETE' THEN\n      v_resource_name := v_old_data->>'name';\n    ELSE\n      v_resource_name := v_new_data->>'name';\n    END IF;\n  ELSIF TG_TABLE_NAME = 'call_logs' THEN\n    v_resource_name := COALESCE(v_new_data->>'lead_name', v_old_data->>'lead_name');\n  ELSIF TG_TABLE_NAME = 'contact_files' OR TG_TABLE_NAME = 'contact_photos' THEN\n    v_resource_name := COALESCE(v_new_data->>'file_name', v_old_data->>'file_name', v_new_data->>'filename', v_old_data->>'filename');\n  ELSIF TG_TABLE_NAME = 'followups' THEN\n    v_resource_name := COALESCE(v_new_data->>'title', v_old_data->>'title');\n  ELSIF TG_TABLE_NAME = 'profiles' THEN\n    v_resource_name := COALESCE(v_new_data->>'name', v_old_data->>'name');\n  END IF;\n\n  IF v_tenant_id IS NOT NULL THEN\n    SELECT t.name INTO v_tenant_name FROM tenants t WHERE t.id = v_tenant_id;\n  END IF;\n\n  IF TG_OP = 'UPDATE' THEN\n    FOR v_key IN SELECT jsonb_object_keys(v_new_data)\n    LOOP\n      IF v_key = ANY(v_skip_fields) THEN CONTINUE; END IF;\n      IF (v_old_data->v_key)::TEXT IS DISTINCT FROM (v_new_data->v_key)::TEXT THEN\n        v_old_changed := v_old_changed || jsonb_build_object(v_key, v_old_data->v_key);\n        v_new_changed := v_new_changed || jsonb_build_object(v_key, v_new_data->v_key);\n        v_change_parts := v_change_parts || (\n          replace(v_key, '_', ' ') || ': ' ||\n          COALESCE(LEFT(v_old_data->>v_key, 80), '(empty)') || ' -> ' ||\n          COALESCE(LEFT(v_new_data->>v_key, 80), '(empty)')\n        );\n      END IF;\n    END LOOP;\n    IF v_old_changed = '{}'::JSONB THEN\n      RETURN NEW;\n    END IF;\n  ELSE\n    IF TG_OP = 'INSERT' THEN\n      v_new_changed := jsonb_build_object(\n        'name', v_new_data->>'name',\n        'email', v_new_data->>'email',\n        'phone', v_new_data->>'phone',\n        'status', COALESCE(v_new_data->>'contact_status', v_new_data->>'status', v_new_data->>'outcome'),\n        'assigned_to', v_new_data->>'assigned_to',\n        'source', v_new_data->>'source'\n      );\n    ELSIF TG_OP = 'DELETE' THEN\n      v_old_changed := jsonb_build_object(\n        'name', v_old_data->>'name',\n        'email', v_old_data->>'email',\n        'phone', v_old_data->>'phone',\n        'status', COALESCE(v_old_data->>'contact_status', v_old_data->>'status')\n      );\n    END IF;\n  END IF;\n\n  v_summary := COALESCE(v_user_name, v_user_email, 'System') || ' ';\n  IF TG_OP = 'INSERT' THEN\n    v_summary := v_summary || 'created ' || replace(TG_TABLE_NAME, '_', ' ');\n    IF v_resource_name IS NOT NULL THEN v_summary := v_summary || ' \"' || v_resource_name || '\"'; END IF;\n  ELSIF TG_OP = 'UPDATE' THEN\n    v_summary := v_summary || 'updated ' || replace(TG_TABLE_NAME, '_', ' ');\n    IF v_resource_name IS NOT NULL THEN v_summary := v_summary || ' \"' || v_resource_name || '\"'; END IF;\n    IF array_length(v_change_parts, 1) > 0 THEN v_summary := v_summary || ' -- ' || array_to_string(v_change_parts, '; '); END IF;\n  ELSIF TG_OP = 'DELETE' THEN\n    v_summary := v_summary || 'deleted ' || replace(TG_TABLE_NAME, '_', ' ');\n    IF v_resource_name IS NOT NULL THEN v_summary := v_summary || ' \"' || v_resource_name || '\"'; END IF;\n  END IF;\n  IF v_tenant_name IS NOT NULL THEN v_summary := v_summary || ' in ' || v_tenant_name; END IF;\n\n  INSERT INTO comprehensive_audit_logs (\n    user_id, user_email, user_name, tenant_id,\n    event_type, event_category, event_action,\n    resource_type, resource_id, resource_name,\n    old_value, new_value, human_summary, changed_fields,\n    metadata, severity\n  ) VALUES (\n    v_user_id, v_user_email, v_user_name, v_tenant_id,\n    CASE TG_OP WHEN 'INSERT' THEN 'data_create' WHEN 'UPDATE' THEN 'data_update' WHEN 'DELETE' THEN 'data_delete' END,\n    'data',\n    lower(TG_OP) || '_' || TG_TABLE_NAME,\n    TG_TABLE_NAME,\n    COALESCE(v_resource_id, 'unknown'),\n    v_resource_name,\n    CASE WHEN TG_OP = 'UPDATE' THEN v_old_changed WHEN TG_OP = 'DELETE' THEN v_old_changed ELSE NULL END,\n    CASE WHEN TG_OP = 'UPDATE' THEN v_new_changed WHEN TG_OP = 'INSERT' THEN v_new_changed ELSE NULL END,\n    v_summary,\n    CASE WHEN TG_OP = 'UPDATE' THEN\n      (SELECT jsonb_agg(k) FROM jsonb_object_keys(v_old_changed) AS k)\n    ELSE NULL END,\n    jsonb_build_object('table_schema', TG_TABLE_SCHEMA, 'trigger_name', TG_NAME, 'operation', TG_OP, 'tenant_name', v_tenant_name),\n    CASE WHEN TG_OP = 'DELETE' THEN 'warn' ELSE 'info' END\n  );\n\n  IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF;\nEND;\n$function$\n","identity_arguments":""},{"name":"compute_primary_role_for_user","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.compute_primary_role_for_user(_user_id uuid)\n RETURNS text\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT ur.role::text\n  FROM public.user_roles ur\n  WHERE ur.user_id = _user_id\n    AND (\n      coalesce(auth.role(), '') = 'service_role'\n      OR auth.uid() = _user_id\n      OR public.is_system_admin(auth.uid())\n      OR public.shares_tenant_as_manager_pm(auth.uid(), _user_id)\n    )\n  ORDER BY CASE ur.role::text\n    WHEN 'GodMode' THEN 1 WHEN 'Admin' THEN 2 WHEN 'Owner' THEN 3\n    WHEN 'Manager' THEN 4 WHEN 'Rep' THEN 5 ELSE 99 END\n  LIMIT 1;\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"compute_visible_courses","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.compute_visible_courses(_user_id uuid, _tenant_org_id text)\n RETURNS TABLE(course_id uuid, is_required boolean, source text, due_at timestamp with time zone)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT (\n           auth.uid() = _user_id\n           AND coalesce(public.is_tenant_member(_tenant_org_id), false)\n         )\n         AND NOT coalesce(public.can_view_tenant_member_academy(auth.uid(), _user_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'academy visibility access denied' USING ERRCODE = '42501';\n  END IF;\n\n  RETURN QUERY\n  SELECT DISTINCT c.id, r.is_required, 'rule'::text,\n         CASE WHEN r.due_days IS NOT NULL THEN now() + make_interval(days => r.due_days) END\n  FROM public.academy_assignment_rules r\n  JOIN public.academy_courses c ON c.id = r.course_id\n  WHERE r.tenant_org_id = _tenant_org_id\n    AND c.scope = 'tenant'\n    AND c.review_status = 'active'\n    AND c.is_published = true\n    AND EXISTS (\n      SELECT 1 FROM public.user_tenant_access uta\n      WHERE uta.user_id = _user_id\n        AND uta.tenant_id::text = _tenant_org_id\n        AND uta.effective_role = r.role\n    )\n    AND (\n      coalesce(array_length(c.required_module_keys, 1), 0) = 0\n      OR EXISTS (\n        SELECT 1 FROM public.academy_tenant_modules tm\n        WHERE tm.tenant_org_id = _tenant_org_id\n          AND tm.enabled = true\n          AND tm.module_key = ANY (c.required_module_keys)\n      )\n    )\n  UNION\n  SELECT a.course_id, true, 'assignment'::text, a.due_at\n  FROM public.academy_user_assignments a\n  JOIN public.academy_courses c ON c.id = a.course_id\n  WHERE a.tenant_org_id = _tenant_org_id\n    AND a.user_id = _user_id\n    AND c.review_status <> 'retired';\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_org_id text"},{"name":"consume_mobile_vendor_loyalty_login_challenge","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.consume_mobile_vendor_loyalty_login_challenge(_tenant_org_id uuid, _challenge_id uuid, _member_id uuid, _expected_attempts integer, _token_hash text, _expires_at timestamp with time zone)\n RETURNS boolean\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_challenge_id uuid;\nbegin\n  update public.mobile_vendor_loyalty_login_challenges\n  set attempts = attempts + 1, consumed_at = now()\n  where tenant_org_id = _tenant_org_id and id = _challenge_id and member_id = _member_id\n    and consumed_at is null and attempts = _expected_attempts and attempts < max_attempts and expires_at > now()\n  returning id into v_challenge_id;\n  if v_challenge_id is null then return false; end if;\n\n  insert into public.mobile_vendor_loyalty_sessions (tenant_org_id, member_id, token_hash, expires_at, last_seen_at)\n  values (_tenant_org_id, _member_id, _token_hash, _expires_at, now());\n  return true;\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _challenge_id uuid, _member_id uuid, _expected_attempts integer, _token_hash text, _expires_at timestamp with time zone"},{"name":"copy_templates_to_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.copy_templates_to_tenant(p_tenant_id text, p_tenancy_type text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\ndeclare\n  v_copied_stages integer := 0;\n  v_copied_scripts integer := 0;\n  v_copied_dialogues integer := 0;\nbegin\n  perform public.require_platform_operator();\n\n  insert into public.pipeline_stages (\n    tenant_org_id, tenancy_type, pipeline_kind, name, color, order_index,\n    is_active, is_closed, is_won, is_template\n  )\n  select p_tenant_id, p_tenancy_type, pipeline_kind, name, color, order_index,\n    is_active, is_closed, is_won, false\n  from public.pipeline_stages\n  where is_template = true and tenancy_type = p_tenancy_type\n    and tenant_org_id is null\n  on conflict do nothing;\n  get diagnostics v_copied_stages = row_count;\n\n  insert into public.call_scripts (\n    tenant_org_id, tenancy_type, script_name, script_type, script_content,\n    prompts, is_template, is_active, order_index\n  )\n  select p_tenant_id, p_tenancy_type, script_name, script_type, script_content,\n    prompts, false, is_active, order_index\n  from public.call_scripts\n  where is_template = true and tenancy_type = p_tenancy_type\n    and tenant_org_id is null\n  on conflict do nothing;\n  get diagnostics v_copied_scripts = row_count;\n\n  insert into public.workflow_dialogue_stages (\n    tenant_org_id, tenancy_type, workflow_id, stage_name, stage_order,\n    script_text, prompts, is_active, is_template\n  )\n  select p_tenant_id, p_tenancy_type, workflow_id, stage_name, stage_order,\n    script_text, prompts, is_active, false\n  from public.workflow_dialogue_stages\n  where is_template = true and tenancy_type = p_tenancy_type\n    and tenant_org_id is null\n  on conflict do nothing;\n  get diagnostics v_copied_dialogues = row_count;\n\n  return jsonb_build_object(\n    'ok', true,\n    'copied_stages', v_copied_stages,\n    'copied_scripts', v_copied_scripts,\n    'copied_dialogues', v_copied_dialogues,\n    'tenant_id', p_tenant_id,\n    'tenancy_type', p_tenancy_type\n  );\nend;\n$function$\n","identity_arguments":"p_tenant_id text, p_tenancy_type text"},{"name":"create_command_center_mission","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.create_command_center_mission(_tenant_id uuid, _objective text, _mission_type text DEFAULT 'platform_operation'::text, _priority text DEFAULT 'task'::text, _context jsonb DEFAULT '{}'::jsonb)\n RETURNS command_center_events\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _uid uuid := auth.uid();\n  _event public.command_center_events;\nBEGIN\n  IF _uid IS NULL OR NOT public.is_command_agent(_uid, _tenant_id) THEN\n    RAISE EXCEPTION 'not_authorized';\n  END IF;\n  IF nullif(trim(_objective), '') IS NULL THEN\n    RAISE EXCEPTION 'objective_required';\n  END IF;\n\n  INSERT INTO public.command_center_events (\n    tenant_id, created_by_user_id, created_by_role, source_module, event_type,\n    priority, title, message, status, requires_response, requires_approval,\n    approval_status, actor_type, actor_display_name, mission_type, mission_phase,\n    mission_status, owner_authorized, authorization_scope, current_step,\n    queue_deadline, execution_deadline, last_progress_at, mission_context\n  ) VALUES (\n    _tenant_id, _uid, 'GodMode', 'system', 'owner_mission',\n    _priority, left(trim(_objective), 140), trim(_objective), 'in_progress', true, false,\n    'approved', 'human', 'Owner', _mission_type, 'objective_received',\n    'accepted', true, 'Owner objective and all reasonably necessary safe supporting work', 0,\n    now() + interval '5 minutes', now() + interval '4 hours', now(), coalesce(_context, '{}'::jsonb)\n  ) RETURNING * INTO _event;\n\n  INSERT INTO public.command_center_mission_steps\n    (tenant_id, command_center_event_id, step_order, step_key, title, lane, status, idempotency_key, input, deadline_at)\n  VALUES\n    (_tenant_id, _event.id, 10, 'preflight', 'Inspect current truth and establish execution plan', 'command-center-autopilot', 'ready', 'mission:' || _event.id || ':preflight', _context, now() + interval '10 minutes'),\n    (_tenant_id, _event.id, 20, 'implementation', 'Prepare the bounded implementation change', 'cc-execution', 'pending', 'mission:' || _event.id || ':implementation', _context, now() + interval '2 hours'),\n    (_tenant_id, _event.id, 30, 'pull_request', 'Open and evaluate the exact pull request', 'cc-execution', 'pending', 'mission:' || _event.id || ':pull_request', _context, now() + interval '2 hours 30 minutes'),\n    (_tenant_id, _event.id, 40, 'release', 'Merge and deploy through the canonical release conductor', 'production-release-conductor', 'pending', 'mission:' || _event.id || ':release', _context, now() + interval '3 hours'),\n    (_tenant_id, _event.id, 50, 'runtime_proof', 'Verify immutable production runtime identity', 'cc-execution', 'pending', 'mission:' || _event.id || ':runtime_proof', _context, now() + interval '3 hours 30 minutes'),\n    (_tenant_id, _event.id, 60, 'visual_proof', 'Run owner-requested authenticated visual acceptance when required', 'onrunner', 'pending', 'mission:' || _event.id || ':visual_proof', _context, now() + interval '4 hours');\n\n  RETURN _event;\nEND;\n$function$\n","identity_arguments":"_tenant_id uuid, _objective text, _mission_type text, _priority text, _context jsonb"},{"name":"create_job_from_contact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.create_job_from_contact(_contact_id uuid)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_contact public.unified_contacts%ROWTYPE;\n  v_tenant uuid;\n  v_job_id uuid;\n  v_uid uuid := auth.uid();\nBEGIN\n  SELECT * INTO v_contact FROM public.unified_contacts WHERE id = _contact_id;\n  IF NOT FOUND THEN RAISE EXCEPTION 'Contact % not found', _contact_id; END IF;\n\n  v_tenant := v_contact.tenant_org_id::uuid;\n\n  IF NOT (public.is_system_admin(v_uid) OR public.is_manager_or_higher(v_uid, v_tenant)) THEN\n    RAISE EXCEPTION 'Not authorized to create jobs for tenant %', v_tenant;\n  END IF;\n\n  -- Idempotent: return existing if already created\n  SELECT id INTO v_job_id FROM public.jobs\n    WHERE tenant_id = v_tenant AND contact_id = _contact_id\n    ORDER BY created_at ASC LIMIT 1;\n  IF v_job_id IS NOT NULL THEN RETURN v_job_id; END IF;\n\n  INSERT INTO public.jobs (\n    tenant_id, contact_id, customer_name, customer_phone,\n    property_address, city, state, zip,\n    job_type, status,\n    scheduled_date, appointment_date,\n    assigned_crew_id, created_by\n  ) VALUES (\n    v_tenant, _contact_id,\n    COALESCE(NULLIF(v_contact.name,''), trim(coalesce(v_contact.first_name,'')||' '||coalesce(v_contact.last_name,''))),\n    v_contact.phone,\n    COALESCE(v_contact.address, ''), v_contact.city, v_contact.state, v_contact.zip,\n    'tarp', 'scheduled',\n    COALESCE(v_contact.appt_date, CURRENT_DATE), v_contact.appt_date::timestamptz,\n    NULL, v_uid\n  ) RETURNING id INTO v_job_id;\n\n  RETURN v_job_id;\nEND $function$\n","identity_arguments":"_contact_id uuid"},{"name":"create_notification_for_user","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.create_notification_for_user(p_user_id uuid, p_tenant_id uuid, p_type text, p_title text, p_message text DEFAULT NULL::text, p_link text DEFAULT NULL::text, p_metadata jsonb DEFAULT NULL::jsonb)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_caller uuid := auth.uid();\n  v_id uuid;\nBEGIN\n  IF v_caller IS NULL THEN\n    RAISE EXCEPTION 'not authenticated';\n  END IF;\n\n  -- Caller must share the tenant with the recipient (tenant isolation guard).\n  IF p_tenant_id IS NOT NULL THEN\n    IF NOT public.is_tenant_member(v_caller, p_tenant_id) THEN\n      RAISE EXCEPTION 'caller not a member of tenant';\n    END IF;\n    IF NOT public.is_tenant_member(p_user_id, p_tenant_id) THEN\n      RAISE EXCEPTION 'recipient not a member of tenant';\n    END IF;\n  END IF;\n\n  INSERT INTO public.notifications (user_id, tenant_id, type, title, message, link, metadata)\n  VALUES (p_user_id, p_tenant_id, p_type, p_title, p_message, p_link, p_metadata)\n  RETURNING id INTO v_id;\n\n  RETURN v_id;\nEND;\n$function$\n","identity_arguments":"p_user_id uuid, p_tenant_id uuid, p_type text, p_title text, p_message text, p_link text, p_metadata jsonb"},{"name":"create_or_resume_command_center_agent_mission","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.create_or_resume_command_center_agent_mission(_mission_key text, _objective text, _tenant_ref text DEFAULT NULL::text, _mission_type text DEFAULT 'platform_operation'::text, _context jsonb DEFAULT '{}'::jsonb)\n RETURNS command_center_events\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'extensions'\nAS $function$\ndeclare\n  _existing public.command_center_events;\n  _target_tenant_id uuid;\n  _target_tenant_name text;\n  _target_tenant_slug text;\n  _anchor_tenant_id uuid;\n  _anchor_owner_id uuid;\n  _creator_id uuid;\n  _scope text;\n  _merged_context jsonb;\n  _normalized_ref text;\n  _resolution_status text := 'not_requested';\n  _resolution_confidence double precision;\n  _resolution_method text;\n  _resolution_candidates jsonb := '[]'::jsonb;\n  _second_confidence double precision;\nbegin\n  if nullif(trim(_mission_key), '') is null then\n    raise exception 'mission_key_required';\n  end if;\n  if nullif(trim(_objective), '') is null then\n    raise exception 'objective_required';\n  end if;\n\n  select * into _existing\n  from public.command_center_events\n  where event_type = 'owner_mission'\n    and mission_context->>'mission_key' = trim(_mission_key)\n  order by created_at desc\n  limit 1;\n\n  if found then\n    return _existing;\n  end if;\n\n  _normalized_ref := public.command_center_normalize_tenant_ref(_tenant_ref);\n  if _normalized_ref <> '' then\n    with resolved as materialized (\n      select r.tenant_id, r.tenant_name, r.company_slug, r.confidence, r.match_kind\n      from public.resolve_command_center_tenant_reference(_tenant_ref) r\n      order by r.confidence desc, r.tenant_name asc\n      limit 3\n    ), packed as (\n      select coalesce(\n        jsonb_agg(\n          jsonb_build_object(\n            'tenant_id', tenant_id,\n            'name', tenant_name,\n            'slug', company_slug,\n            'confidence', round(confidence::numeric, 4),\n            'match_kind', match_kind\n          ) order by confidence desc, tenant_name asc\n        ),\n        '[]'::jsonb\n      ) as candidates\n      from resolved\n    )\n    select\n      candidates,\n      nullif(candidates->0->>'tenant_id', '')::uuid,\n      candidates->0->>'name',\n      candidates->0->>'slug',\n      nullif(candidates->0->>'confidence', '')::double precision,\n      candidates->0->>'match_kind',\n      nullif(candidates->1->>'confidence', '')::double precision\n    into _resolution_candidates, _target_tenant_id, _target_tenant_name, _target_tenant_slug,\n         _resolution_confidence, _resolution_method, _second_confidence\n    from packed;\n\n    if _target_tenant_id is not null\n       and _resolution_confidence >= 0.88\n       and (_second_confidence is null or _resolution_confidence - _second_confidence >= 0.08)\n    then\n      _resolution_status := 'resolved';\n    else\n      _target_tenant_id := null;\n      _target_tenant_name := null;\n      _target_tenant_slug := null;\n      _resolution_status := case\n        when jsonb_array_length(_resolution_candidates) > 0 then 'ambiguous'\n        else 'unresolved'\n      end;\n    end if;\n  end if;\n\n  if _target_tenant_id is not null then\n    select id, owner_id into _anchor_tenant_id, _anchor_owner_id\n    from public.tenants where id = _target_tenant_id;\n    _scope := 'tenant';\n  else\n    select id, owner_id into _anchor_tenant_id, _anchor_owner_id\n    from public.tenants\n    where company_slug = 'knocklaunch-crm' and status = 'active'\n    order by created_at asc\n    limit 1;\n    if _anchor_tenant_id is null then raise exception 'platform_mission_anchor_unavailable'; end if;\n    _scope := 'platform';\n  end if;\n\n  if _anchor_tenant_id is null then raise exception 'mission_anchor_tenant_unavailable'; end if;\n\n  select id into _creator_id\n  from public.profiles\n  where lower(coalesce(email, '')) = 'info@knocklaunch.app'\n  limit 1;\n  _creator_id := coalesce(_creator_id, _anchor_owner_id);\n  if _creator_id is null then raise exception 'mission_owner_identity_unavailable'; end if;\n\n  if _resolution_status = 'resolved' and _resolution_confidence >= 0.90 and _normalized_ref <> '' then\n    insert into public.command_center_tenant_aliases(\n      tenant_id, alias, normalized_alias, source, confidence, use_count, last_used_at\n    )\n    values(\n      _target_tenant_id, trim(_tenant_ref), _normalized_ref,\n      'adaptive_high_confidence', _resolution_confidence, 1, now()\n    )\n    on conflict(tenant_id, normalized_alias) do update\n    set alias = excluded.alias,\n        confidence = greatest(public.command_center_tenant_aliases.confidence, excluded.confidence),\n        use_count = public.command_center_tenant_aliases.use_count + 1,\n        last_used_at = now();\n  end if;\n\n  _merged_context := coalesce(_context, '{}'::jsonb) || jsonb_strip_nulls(jsonb_build_object(\n    'mission_key', trim(_mission_key), 'scope', _scope,\n    'target_tenant_id', _target_tenant_id, 'target_tenant_name', _target_tenant_name,\n    'target_tenant_slug', _target_tenant_slug,\n    'tenant_reference_input', nullif(trim(_tenant_ref), ''),\n    'tenant_reference_normalized', nullif(_normalized_ref, ''),\n    'tenant_resolution_status', _resolution_status,\n    'tenant_resolution_confidence', _resolution_confidence,\n    'tenant_resolution_method', _resolution_method,\n    'tenant_resolution_candidates', _resolution_candidates,\n    'anchor_tenant_id', _anchor_tenant_id, 'silent', true,\n    'supervisor_owner', 'cc-execution',\n    'conversation_metrics', jsonb_build_object(\n      'tool_call_count', 0, 'repeated_call_count', 0, 'receipt_bytes', 0,\n      'release_count', 0, 'owner_interruption_count', 0, 'tool_call_keys', '[]'::jsonb\n    )\n  ));\n\n  begin\n    insert into public.command_center_events(\n      tenant_id, created_by_user_id, created_by_role, source_module, event_type,\n      priority, title, message, status, requires_response, requires_approval,\n      approval_status, actor_type, actor_display_name, mission_type, mission_phase,\n      mission_status, owner_authorized, authorization_scope, current_step,\n      queue_deadline, execution_deadline, started_at, last_progress_at,\n      leased_by, lease_expires_at, mission_context\n    )\n    values(\n      _anchor_tenant_id, _creator_id, 'GodMode', 'system', 'owner_mission',\n      'task', left(trim(_objective), 140), trim(_objective), 'in_progress', true,\n      false, 'approved', 'human', 'Owner',\n      coalesce(nullif(trim(_mission_type), ''), 'platform_operation'),\n      'objective_received', 'accepted', true,\n      'Owner objective and all reasonably necessary safe supporting work',\n      0, now() + interval '5 minutes', now() + interval '4 hours', now(), now(),\n      'cc-execution-objective-supervisor', now() + interval '4 hours', _merged_context\n    ) returning * into _existing;\n  exception when unique_violation then\n    select * into _existing\n    from public.command_center_events\n    where event_type = 'owner_mission' and mission_context->>'mission_key' = trim(_mission_key)\n    order by created_at desc limit 1;\n  end;\n\n  insert into public.command_center_mission_steps(\n    tenant_id, command_center_event_id, step_order, step_key, title, lane,\n    status, idempotency_key, input, deadline_at\n  ) values\n    (_anchor_tenant_id, _existing.id, 10, 'preflight', 'Inspect current truth and establish execution plan', 'cc-execution', 'ready', 'mission:' || _existing.id || ':preflight', _merged_context, now() + interval '10 minutes'),\n    (_anchor_tenant_id, _existing.id, 20, 'implementation', 'Prepare the bounded implementation change', 'cc-execution', 'pending', 'mission:' || _existing.id || ':implementation', _merged_context, now() + interval '2 hours'),\n    (_anchor_tenant_id, _existing.id, 30, 'pull_request', 'Open and evaluate the exact pull request', 'cc-execution', 'pending', 'mission:' || _existing.id || ':pull_request', _merged_context, now() + interval '2 hours 30 minutes'),\n    (_anchor_tenant_id, _existing.id, 40, 'release', 'Merge and deploy through the canonical release conductor', 'production-release-conductor', 'pending', 'mission:' || _existing.id || ':release', _merged_context, now() + interval '3 hours'),\n    (_anchor_tenant_id, _existing.id, 50, 'runtime_proof', 'Verify immutable production runtime identity', 'cc-execution', 'pending', 'mission:' || _existing.id || ':runtime_proof', _merged_context, now() + interval '3 hours 30 minutes'),\n    (_anchor_tenant_id, _existing.id, 60, 'visual_proof', 'Run owner-requested authenticated visual acceptance when required', 'onrunner', 'pending', 'mission:' || _existing.id || ':visual_proof', _merged_context, now() + interval '4 hours')\n  on conflict(command_center_event_id, step_key) do nothing;\n\n  return _existing;\nend;\n$function$\n","identity_arguments":"_mission_key text, _objective text, _tenant_ref text, _mission_type text, _context jsonb"},{"name":"create_security_alert","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.create_security_alert(p_alert_type text, p_severity text, p_title text, p_description text DEFAULT NULL::text, p_user_id uuid DEFAULT NULL::uuid, p_user_email text DEFAULT NULL::text, p_tenant_id uuid DEFAULT NULL::uuid, p_ip_address text DEFAULT NULL::text, p_user_agent text DEFAULT NULL::text, p_metadata jsonb DEFAULT '{}'::jsonb)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE v_alert_id UUID;\nBEGIN\n  INSERT INTO security_alerts (alert_type, severity, title, description, user_id, user_email, tenant_id, ip_address, user_agent, metadata)\n  VALUES (p_alert_type, p_severity, p_title, p_description, p_user_id, p_user_email, p_tenant_id, p_ip_address, p_user_agent, p_metadata) RETURNING id INTO v_alert_id;\n  INSERT INTO comprehensive_audit_logs (user_id, tenant_id, event_type, event_category, event_action, resource_type, resource_id, metadata, severity)\n  VALUES (p_user_id, p_tenant_id, 'error', 'system', 'security_alert_created', 'security_alert', v_alert_id::TEXT, jsonb_build_object('alert_type', p_alert_type, 'title', p_title), p_severity);\n  RETURN v_alert_id;\nEND; $function$\n","identity_arguments":"p_alert_type text, p_severity text, p_title text, p_description text, p_user_id uuid, p_user_email text, p_tenant_id uuid, p_ip_address text, p_user_agent text, p_metadata jsonb"},{"name":"decrement_active_enrollments","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.decrement_active_enrollments(p_sequence_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  UPDATE communication_sequences\n  SET active_enrollments = GREATEST(0, COALESCE(active_enrollments, 0) - 1)\n  WHERE id = p_sequence_id;\nEND;\n$function$\n","identity_arguments":"p_sequence_id uuid"},{"name":"delete_email","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.delete_email(queue_name text, message_id bigint)\n RETURNS boolean\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\nBEGIN\n  RETURN pgmq.delete(queue_name, message_id);\nEXCEPTION WHEN undefined_table THEN\n  RETURN FALSE;\nEND;\n$function$\n","identity_arguments":"queue_name text, message_id bigint"},{"name":"derive_onboarding_blueprint","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.derive_onboarding_blueprint(p_session_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE s public.onboarding_sessions%rowtype; v_type text; v_track text; v_blueprint jsonb;\nBEGIN\n  SELECT * INTO s FROM public.onboarding_sessions WHERE id=p_session_id;\n  IF NOT FOUND THEN RAISE EXCEPTION 'Onboarding session not found'; END IF;\n  IF coalesce(auth.role(),'') <> 'service_role' THEN IF auth.uid() IS NULL OR (s.owner_user_id IS DISTINCT FROM auth.uid() AND NOT public.is_system_admin(auth.uid())) THEN RAISE EXCEPTION 'Not authorized for this onboarding session' USING ERRCODE='42501'; END IF; END IF;\n  v_type:=public.canonical_tenant_type(s.requested_business_type);\n  IF v_type IS NULL THEN RAISE EXCEPTION 'A supported business type must be explicitly selected before deriving an onboarding blueprint.' USING ERRCODE='22023'; END IF;\n  v_track:=public.academy_track_for_type(v_type);\n  v_blueprint:=jsonb_build_object('version','knocklaunch.onboarding.blueprint.v1','tenant_type',v_type,'academy_track',v_track,'service_lines',s.service_lines,'goals',s.goals,'requested_capabilities',s.requested_capabilities,'recommended_capabilities',jsonb_build_object('mail',true,'sms',v_type IN ('ROOFING_COMPANY','PUBLIC_ADJUSTER_FIRM','MITIGATION'),'calling',v_type IN ('ROOFING_COMPANY','PUBLIC_ADJUSTER_FIRM','MITIGATION'),'payments',v_type IN ('ROOFING_COMPANY','MOBILE_VENDOR','CAFE_QSR','TIRE_SHOP','AUTO_DETAILING'),'calendar',true,'documents',true),'operating_states',to_jsonb(s.operating_states),'service_area',s.service_area,'team_size',s.team_size);\n  UPDATE public.onboarding_sessions SET canonical_tenant_type=v_type,academy_track=v_track,derived_blueprint=v_blueprint,updated_at=now() WHERE id=p_session_id;\n  RETURN v_blueprint;\nEND;\n$function$\n","identity_arguments":"p_session_id uuid"},{"name":"detect_revocation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.detect_revocation(p_text text)\n RETURNS TABLE(revoked boolean, matched_keyword text)\n LANGUAGE plpgsql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_clean TEXT;\n  v_keywords TEXT[] := ARRAY['stop','stopall','unsubscribe','cancel','end','quit','revoke','remove me','take me off','do not call','dont call','don''t call','no more calls','no more texts','opt out','opt-out','stop calling','stop texting','leave me alone','never call'];\n  v_kw TEXT;\nBEGIN\n  IF p_text IS NULL OR length(trim(p_text)) = 0 THEN RETURN QUERY SELECT false, NULL::TEXT; RETURN; END IF;\n  v_clean := lower(regexp_replace(trim(p_text), '\\s+', ' ', 'g'));\n  IF v_clean IN ('stop','stopall','unsubscribe','cancel','end','quit','revoke') THEN RETURN QUERY SELECT true, v_clean; RETURN; END IF;\n  FOREACH v_kw IN ARRAY v_keywords LOOP\n    IF position(v_kw IN v_clean) > 0 THEN RETURN QUERY SELECT true, v_kw; RETURN; END IF;\n  END LOOP;\n  RETURN QUERY SELECT false, NULL::TEXT;\nEND; $function$\n","identity_arguments":"p_text text"},{"name":"dispatch_homeowner_claim_stage_update","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.dispatch_homeowner_claim_stage_update()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_url text;\n  v_key text;\n  v_payload jsonb;\nBEGIN\n  IF NEW.claim_status IS NULL OR NEW.claim_status = COALESCE(OLD.claim_status, '') THEN\n    RETURN NEW;\n  END IF;\n\n  IF NOT EXISTS (\n    SELECT 1\n    FROM public.unified_contacts\n    WHERE id::text = NEW.contact_id::text\n  ) THEN\n    RETURN NEW;\n  END IF;\n\n  BEGIN\n    SELECT decrypted_secret INTO v_url FROM vault.decrypted_secrets WHERE name = 'project_url' LIMIT 1;\n    SELECT decrypted_secret INTO v_key FROM vault.decrypted_secrets WHERE name = 'service_role_key' LIMIT 1;\n  EXCEPTION WHEN OTHERS THEN\n    RAISE NOTICE 'dispatch_homeowner_claim_stage_update: vault unavailable, skipping';\n    RETURN NEW;\n  END;\n\n  IF v_url IS NULL OR v_key IS NULL THEN\n    RAISE NOTICE 'dispatch_homeowner_claim_stage_update: missing url/key, skipping';\n    RETURN NEW;\n  END IF;\n\n  v_payload := jsonb_build_object(\n    'action', 'trigger',\n    'event', jsonb_build_object(\n      'type', 'stage_change',\n      'contactId', NEW.contact_id,\n      'tenantId', NEW.tenant_org_id,\n      'oldValue', OLD.claim_status,\n      'newValue', NEW.claim_status,\n      'field', 'claim_stage',\n      'metadata', jsonb_build_object('pipeline_kind', 'CLAIM', 'claim_id', NEW.id)\n    )\n  );\n\n  PERFORM net.http_post(\n    url := v_url || '/functions/v1/pipeline-automation',\n    headers := jsonb_build_object(\n      'Content-Type', 'application/json',\n      'Authorization', 'Bearer ' || v_key\n    ),\n    body := v_payload\n  );\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"dispatch_homeowner_stage_update","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.dispatch_homeowner_stage_update()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_old TEXT;\n  v_new TEXT;\n  v_kind TEXT;\n  v_supabase_url TEXT;\n  v_service_key TEXT;\n  v_payload JSONB;\nBEGIN\n  IF TG_OP <> 'UPDATE' THEN RETURN NEW; END IF;\n\n  IF NEW.lead_stage IS DISTINCT FROM OLD.lead_stage THEN\n    v_old := OLD.lead_stage; v_new := NEW.lead_stage; v_kind := 'LEAD';\n  ELSIF NEW.claim_stage IS DISTINCT FROM OLD.claim_stage THEN\n    v_old := OLD.claim_stage; v_new := NEW.claim_stage; v_kind := 'CLAIM';\n  ELSIF NEW.jobs_stage IS DISTINCT FROM OLD.jobs_stage THEN\n    v_old := OLD.jobs_stage; v_new := NEW.jobs_stage; v_kind := 'JOB';\n  ELSE\n    RETURN NEW;\n  END IF;\n\n  IF v_new IS NULL OR v_new = '' THEN RETURN NEW; END IF;\n\n  IF NOT EXISTS (\n    SELECT 1 FROM public.homeowner_stage_messages\n    WHERE pipeline_kind = v_kind\n      AND stage_name = v_new\n      AND send_to_homeowner = true\n      AND (tenant_org_id = NEW.tenant_org_id OR tenant_org_id IS NULL)\n  ) THEN\n    RETURN NEW;\n  END IF;\n\n  BEGIN\n    SELECT decrypted_secret INTO v_supabase_url FROM vault.decrypted_secrets WHERE name = 'SUPABASE_URL' LIMIT 1;\n    SELECT decrypted_secret INTO v_service_key FROM vault.decrypted_secrets WHERE name = 'SUPABASE_SERVICE_ROLE_KEY' LIMIT 1;\n  EXCEPTION WHEN OTHERS THEN NULL;\n  END;\n\n  IF v_supabase_url IS NULL OR v_service_key IS NULL THEN\n    RAISE NOTICE 'dispatch_homeowner_stage_update: missing supabase url/key, skipping';\n    RETURN NEW;\n  END IF;\n\n  v_payload := jsonb_build_object(\n    'action','trigger',\n    'event', jsonb_build_object(\n      'type','stage_change',\n      'contactId', NEW.id,\n      'tenantId', NEW.tenant_org_id,\n      'oldValue', v_old,\n      'newValue', v_new,\n      'field', lower(v_kind) || '_stage',\n      'metadata', jsonb_build_object(\n        'pipeline_kind', v_kind,\n        'auto_homeowner_notify', true\n      )\n    )\n  );\n\n  PERFORM net.http_post(\n    url := v_supabase_url || '/functions/v1/pipeline-automation',\n    headers := jsonb_build_object(\n      'Content-Type','application/json',\n      'Authorization','Bearer ' || v_service_key\n    ),\n    body := v_payload\n  );\n\n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  RAISE NOTICE 'dispatch_homeowner_stage_update error: %', SQLERRM;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"dispatch_onboarding_research_task","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.dispatch_onboarding_research_task()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'net'\nAS $function$\nbegin\n  if new.status='pending'\n     and new.provider_key is not null\n     and new.dispatch_token is not null\n     and (tg_op='INSERT' or old.dispatch_token is distinct from new.dispatch_token or old.status is distinct from new.status) then\n    perform net.http_post(\n      url := 'https://ymntrajfubicyxwwdxxa.supabase.co/functions/v1/onboarding-research-runner',\n      body := jsonb_build_object('task_id',new.id,'dispatch_token',new.dispatch_token),\n      headers := jsonb_build_object('Content-Type','application/json'),\n      timeout_milliseconds := 10000\n    );\n  end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"dnc_bulk_upsert_phones","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.dnc_bulk_upsert_phones(_phones text[], _federal boolean, _tenant uuid, _reason text, _added_by text)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  inserted_count integer := 0;\nBEGIN\n  IF _phones IS NULL OR array_length(_phones, 1) IS NULL THEN\n    RETURN 0;\n  END IF;\n\n  IF _federal THEN\n    WITH ins AS (\n      INSERT INTO public.dnc_federal_numbers (phone, area_code, source)\n      SELECT p, left(p, 3), 'ftc_upload'\n      FROM unnest(_phones) AS p\n      WHERE p ~ '^\\d{10}$'\n      ON CONFLICT (phone) DO NOTHING\n      RETURNING 1\n    )\n    SELECT count(*) INTO inserted_count FROM ins;\n  ELSE\n    IF _tenant IS NULL THEN\n      RAISE EXCEPTION 'tenant_id is required for tenant DNC list imports';\n    END IF;\n    WITH ins AS (\n      INSERT INTO public.dnc_list (phone, phone_normalized, reason, added_by, tenant_org_id)\n      SELECT p, p, COALESCE(_reason, 'Bulk DNC import'), COALESCE(_added_by, 'admin'), _tenant\n      FROM unnest(_phones) AS p\n      WHERE p ~ '^\\d{10}$'\n      ON CONFLICT (phone) DO NOTHING\n      RETURNING 1\n    )\n    SELECT count(*) INTO inserted_count FROM ins;\n  END IF;\n\n  RETURN inserted_count;\nEND;\n$function$\n","identity_arguments":"_phones text[], _federal boolean, _tenant uuid, _reason text, _added_by text"},{"name":"enforce_academy_lesson_grounding","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_academy_lesson_grounding()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_scope text;\nBEGIN\n  SELECT c.scope INTO v_scope\n  FROM public.academy_courses c\n  JOIN public.academy_units u ON u.course_id = c.id\n  WHERE u.id = NEW.unit_id;\n\n  IF v_scope = 'tenant' THEN\n    IF NEW.linked_action_key IS NULL\n       AND NEW.module_key IS NULL\n       AND COALESCE(array_length(NEW.role_scope, 1), 0) = 0\n       AND NEW.workflow_key IS NULL\n       AND NEW.sop_category IS NULL THEN\n      RAISE EXCEPTION 'Tenant-scope lessons must declare at least one of linked_action_key, module_key, role_scope, workflow_key, or sop_category (lesson=\"%\")', NEW.title;\n    END IF;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"enforce_assigned_user_tenant_match","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_assigned_user_tenant_match()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_assignment text;\n  v_user_id uuid;\n  v_tenant_id uuid;\nbegin\n  if new.tenant_org_id is null then\n    return new;\n  end if;\n\n  begin\n    v_tenant_id := new.tenant_org_id::uuid;\n  exception when invalid_text_representation then\n    raise exception 'Invalid tenant identifier on contact assignment'\n      using errcode = 'check_violation';\n  end;\n\n  foreach v_assignment in array array[new.assigned_user, new.assigned_to]\n  loop\n    continue when nullif(btrim(coalesce(v_assignment, '')), '') is null;\n\n    begin\n      v_user_id := v_assignment::uuid;\n    exception when invalid_text_representation then\n      raise exception 'Assignment must reference a valid user identifier'\n        using errcode = 'check_violation';\n    end;\n\n    if not exists (\n      select 1\n      from public.user_tenant_memberships m\n      where m.user_id = v_user_id\n        and m.tenant_id = v_tenant_id\n        and m.status = 'active'\n    ) and not exists (\n      select 1\n      from public.user_roles r\n      where r.user_id = v_user_id\n        and r.tenant_id = v_tenant_id\n    ) then\n      raise exception 'Cross-tenant assignment blocked: user % has no active access to tenant %',\n        v_user_id, v_tenant_id\n        using errcode = 'check_violation';\n    end if;\n  end loop;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"enforce_calendar_claim_context","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_calendar_claim_context()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\ndeclare\n  claim_row public.contact_claims%rowtype;\nbegin\n  if new.claim_id is null then\n    return new;\n  end if;\n\n  select * into claim_row\n  from public.contact_claims\n  where id = new.claim_id;\n\n  if not found then\n    raise exception 'calendar_claim_not_found';\n  end if;\n\n  if new.tenant_org_id::text is distinct from claim_row.tenant_org_id::text then\n    raise exception 'calendar_claim_tenant_mismatch';\n  end if;\n\n  if new.contact_id is null then\n    new.contact_id := claim_row.contact_id;\n  elsif new.contact_id::text is distinct from claim_row.contact_id::text then\n    raise exception 'calendar_claim_contact_mismatch';\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"enforce_dnc_quarantine","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_dnc_quarantine()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_norm TEXT;\n  v_row RECORD;\nBEGIN\n  v_norm := NEW.phone_normalized;\n  IF v_norm IS NULL OR length(v_norm) < 10 THEN\n    RETURN NEW;\n  END IF;\n\n  -- unified_contacts matches\n  FOR v_row IN\n    SELECT * FROM public.unified_contacts\n    WHERE public.normalize_phone_for_dnc(phone) = v_norm\n      AND deleted_at IS NULL\n  LOOP\n    BEGIN\n      IF public.is_existing_client_record(\n        v_row.status, v_row.lead_stage, v_row.jobs_stage, v_row.claim_stage, v_row.graduated_at\n      ) THEN\n        UPDATE public.unified_contacts\n        SET is_dnc = true,\n            dnc_reason = COALESCE(NEW.reason, 'DNC - Existing Client'),\n            dnc_checked_at = now(),\n            updated_at = now()\n        WHERE id = v_row.id;\n      ELSE\n        INSERT INTO public.dnc_quarantine (\n          phone_normalized, original_phone, source_table, source_id, source_lead_id,\n          tenant_org_id, reason, dnc_source, contact_snapshot\n        ) VALUES (\n          v_norm, v_row.phone, 'unified_contacts', v_row.id::text, v_row.lead_id,\n          v_row.tenant_org_id::text, COALESCE(NEW.reason, 'DNC match'), 'internal', to_jsonb(v_row)\n        );\n        DELETE FROM public.unified_contacts WHERE id = v_row.id;\n      END IF;\n    EXCEPTION WHEN OTHERS THEN\n      RAISE WARNING '[enforce_dnc_quarantine] unified_contacts row % failed: %', v_row.id, SQLERRM;\n    END;\n  END LOOP;\n\n  -- lead_deck matches\n  FOR v_row IN\n    SELECT * FROM public.lead_deck\n    WHERE public.normalize_phone_for_dnc(phone) = v_norm\n      AND deleted_at IS NULL\n  LOOP\n    BEGIN\n      IF public.is_existing_client_record(\n        v_row.status, v_row.lead_stage, NULL, NULL, v_row.graduated_at\n      ) THEN\n        UPDATE public.lead_deck\n        SET is_dnc = true,\n            dnc_reason = COALESCE(NEW.reason, 'DNC - Existing Client'),\n            dnc_checked_at = now(),\n            updated_at = now()\n        WHERE id = v_row.id;\n      ELSE\n        INSERT INTO public.dnc_quarantine (\n          phone_normalized, original_phone, source_table, source_id, source_lead_id,\n          tenant_org_id, reason, dnc_source, contact_snapshot\n        ) VALUES (\n          v_norm, v_row.phone, 'lead_deck', v_row.id::text, v_row.lead_id,\n          v_row.tenant_org_id::text, COALESCE(NEW.reason, 'DNC match'), 'internal', to_jsonb(v_row)\n        );\n        DELETE FROM public.lead_deck WHERE id = v_row.id;\n      END IF;\n    EXCEPTION WHEN OTHERS THEN\n      RAISE WARNING '[enforce_dnc_quarantine] lead_deck row % failed: %', v_row.id, SQLERRM;\n    END;\n  END LOOP;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"enforce_job_request_state_machine","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_job_request_state_machine()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  uid uuid := auth.uid();\n  is_elevated boolean := false;\nBEGIN\n  -- Service role / migrations bypass\n  IF uid IS NULL THEN RETURN NEW; END IF;\n\n  -- No status change → nothing to enforce\n  IF NEW.status IS NOT DISTINCT FROM OLD.status THEN RETURN NEW; END IF;\n\n  -- Platform admin / tenant manager+ bypass (audited via standard audit triggers)\n  is_elevated :=\n       public.is_system_admin(uid)\n    OR public.is_manager_or_higher_strict(uid, OLD.tenant_id);\n  IF is_elevated THEN RETURN NEW; END IF;\n\n  -- Terminal states are locked for non-elevated users\n  IF OLD.status IN ('rejected','converted','cancelled') THEN\n    RAISE EXCEPTION 'job_requests.status % is terminal and cannot be changed', OLD.status\n      USING ERRCODE = '42501';\n  END IF;\n\n  -- Legal transitions for non-elevated users\n  IF NOT (\n       (OLD.status = 'pending_review' AND NEW.status IN ('needs_info','approved','rejected','cancelled'))\n    OR (OLD.status = 'needs_info'     AND NEW.status IN ('pending_review','cancelled'))\n    OR (OLD.status = 'approved'       AND NEW.status IN ('converted','cancelled'))\n  ) THEN\n    RAISE EXCEPTION 'illegal job_requests transition % -> %', OLD.status, NEW.status\n      USING ERRCODE = '42501';\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"enforce_job_verify_authority","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_job_verify_authority()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  uid uuid := auth.uid();\n  is_override boolean := COALESCE(NULLIF(current_setting('app.platform_override', true), '')::boolean, false);\n  override_reason text := NULLIF(current_setting('app.platform_override_reason', true), '');\n  actor_email text;\nBEGIN\n  IF NEW.status = 'verified' AND COALESCE(OLD.status, '') <> 'verified' THEN\n    IF uid IS NULL THEN\n      RAISE EXCEPTION 'verify requires authenticated user';\n    END IF;\n\n    -- Strict tenant-scoped authorization (no GodMode-anywhere leakage)\n    IF public.is_manager_or_higher_strict(uid, NEW.tenant_id)\n       OR public.has_acting_pm_grant(uid, NEW.tenant_id) THEN\n      NULL; -- authorized in-tenant\n    ELSIF public.is_platform_admin(uid) AND is_override THEN\n      IF override_reason IS NULL OR length(trim(override_reason)) < 10 THEN\n        RAISE EXCEPTION 'platform override requires reason (>=10 chars)';\n      END IF;\n      SELECT email INTO actor_email FROM auth.users WHERE id = uid;\n      INSERT INTO public.platform_override_log\n        (actor_id, actor_email, tenant_id, action, target_table, target_id, reason, payload)\n      VALUES\n        (uid, actor_email, NEW.tenant_id, 'verify_job', 'jobs', NEW.id::text, override_reason,\n         jsonb_build_object('job_number', NEW.job_number, 'prev_status', OLD.status));\n    ELSE\n      RAISE EXCEPTION 'not authorized to verify jobs in this tenant';\n    END IF;\n\n    NEW.verified_by := COALESCE(NEW.verified_by, uid);\n    NEW.verified_at := COALESCE(NEW.verified_at, now());\n  END IF;\n\n  RETURN NEW;\nEND\n$function$\n","identity_arguments":""},{"name":"enforce_job_verify_checklist","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_job_verify_checklist()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  missing text[] := ARRAY[]::text[];\nBEGIN\n  IF NEW.status = 'verified' AND COALESCE(OLD.status, '') <> 'verified' THEN\n    -- Job must have already been marked completed\n    IF COALESCE(OLD.status, '') <> 'completed' THEN\n      missing := array_append(missing, 'job status must be completed before verification');\n    END IF;\n\n    IF NOT COALESCE(NEW.work_auth_signed, false) THEN\n      missing := array_append(missing, 'Work Authorization signed');\n    END IF;\n\n    IF NOT COALESCE(NEW.photos_uploaded, false) THEN\n      missing := array_append(missing, 'photos uploaded');\n    END IF;\n\n    -- tarp_installed is nullable; only block if explicitly false\n    IF NEW.tarp_installed IS NOT NULL AND NEW.tarp_installed = false THEN\n      missing := array_append(missing, 'tarp installed / work completed');\n    END IF;\n\n    IF NOT COALESCE(NEW.docs_complete, false) THEN\n      missing := array_append(missing, 'docs complete');\n    END IF;\n\n    IF NEW.property_address IS NULL OR length(trim(NEW.property_address)) = 0 THEN\n      missing := array_append(missing, 'property address');\n    END IF;\n\n    IF array_length(missing, 1) > 0 THEN\n      RAISE EXCEPTION 'Cannot verify job: missing required items: %', array_to_string(missing, ', ')\n        USING ERRCODE = '22023';\n    END IF;\n  END IF;\n\n  RETURN NEW;\nEND\n$function$\n","identity_arguments":""},{"name":"enforce_jobs_crew_update_scope","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_jobs_crew_update_scope()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  uid uuid := auth.uid();\n  is_crew_self boolean;\n  is_elevated boolean;\n  bad text[] := ARRAY[]::text[];\n  allowed_status text[] := ARRAY['dispatched','on_site','in_progress','crew_completed'];\nBEGIN\n  IF uid IS NULL THEN RETURN NEW; END IF;\n\n  is_crew_self := (OLD.assigned_crew_id IS NOT NULL AND OLD.assigned_crew_id = uid);\n  IF NOT is_crew_self THEN RETURN NEW; END IF;\n\n  is_elevated :=\n    public.is_system_admin(uid)\n    OR public.is_manager_or_higher_strict(uid, OLD.tenant_id)\n    OR public.has_acting_pm_grant(uid, OLD.tenant_id);\n  IF is_elevated THEN RETURN NEW; END IF;\n\n  IF NEW.tenant_id            IS DISTINCT FROM OLD.tenant_id            THEN bad := array_append(bad,'tenant_id'); END IF;\n  IF NEW.contact_id           IS DISTINCT FROM OLD.contact_id           THEN bad := array_append(bad,'contact_id'); END IF;\n  IF NEW.contact_claim_id     IS DISTINCT FROM OLD.contact_claim_id     THEN bad := array_append(bad,'contact_claim_id'); END IF;\n  IF NEW.appointment_id       IS DISTINCT FROM OLD.appointment_id       THEN bad := array_append(bad,'appointment_id'); END IF;\n  IF NEW.job_number           IS DISTINCT FROM OLD.job_number           THEN bad := array_append(bad,'job_number'); END IF;\n  IF NEW.customer_name        IS DISTINCT FROM OLD.customer_name        THEN bad := array_append(bad,'customer_name'); END IF;\n  IF NEW.customer_phone       IS DISTINCT FROM OLD.customer_phone       THEN bad := array_append(bad,'customer_phone'); END IF;\n  IF NEW.customer_email       IS DISTINCT FROM OLD.customer_email       THEN bad := array_append(bad,'customer_email'); END IF;\n  IF NEW.property_address     IS DISTINCT FROM OLD.property_address     THEN bad := array_append(bad,'property_address'); END IF;\n  IF NEW.city                 IS DISTINCT FROM OLD.city                 THEN bad := array_append(bad,'city'); END IF;\n  IF NEW.state                IS DISTINCT FROM OLD.state                THEN bad := array_append(bad,'state'); END IF;\n  IF NEW.zip                  IS DISTINCT FROM OLD.zip                  THEN bad := array_append(bad,'zip'); END IF;\n  IF NEW.latitude             IS DISTINCT FROM OLD.latitude             THEN bad := array_append(bad,'latitude'); END IF;\n  IF NEW.longitude            IS DISTINCT FROM OLD.longitude            THEN bad := array_append(bad,'longitude'); END IF;\n  IF NEW.job_type             IS DISTINCT FROM OLD.job_type             THEN bad := array_append(bad,'job_type'); END IF;\n  IF NEW.priority             IS DISTINCT FROM OLD.priority             THEN bad := array_append(bad,'priority'); END IF;\n  IF NEW.assigned_crew_id     IS DISTINCT FROM OLD.assigned_crew_id     THEN bad := array_append(bad,'assigned_crew_id'); END IF;\n  IF NEW.assigned_crew_email  IS DISTINCT FROM OLD.assigned_crew_email  THEN bad := array_append(bad,'assigned_crew_email'); END IF;\n  IF NEW.assigned_pm_id       IS DISTINCT FROM OLD.assigned_pm_id       THEN bad := array_append(bad,'assigned_pm_id'); END IF;\n  IF NEW.assigned_pm_email    IS DISTINCT FROM OLD.assigned_pm_email    THEN bad := array_append(bad,'assigned_pm_email'); END IF;\n  IF NEW.scheduled_date       IS DISTINCT FROM OLD.scheduled_date       THEN bad := array_append(bad,'scheduled_date'); END IF;\n  IF NEW.scheduled_time       IS DISTINCT FROM OLD.scheduled_time       THEN bad := array_append(bad,'scheduled_time'); END IF;\n  IF NEW.appointment_date     IS DISTINCT FROM OLD.appointment_date     THEN bad := array_append(bad,'appointment_date'); END IF;\n  IF NEW.verified_at          IS DISTINCT FROM OLD.verified_at          THEN bad := array_append(bad,'verified_at'); END IF;\n  IF NEW.verified_by          IS DISTINCT FROM OLD.verified_by          THEN bad := array_append(bad,'verified_by'); END IF;\n  IF NEW.carrier_name         IS DISTINCT FROM OLD.carrier_name         THEN bad := array_append(bad,'carrier_name'); END IF;\n  IF NEW.policy_number        IS DISTINCT FROM OLD.policy_number        THEN bad := array_append(bad,'policy_number'); END IF;\n  IF NEW.claim_number         IS DISTINCT FROM OLD.claim_number         THEN bad := array_append(bad,'claim_number'); END IF;\n  IF NEW.adjuster_name        IS DISTINCT FROM OLD.adjuster_name        THEN bad := array_append(bad,'adjuster_name'); END IF;\n  IF NEW.adjuster_phone       IS DISTINCT FROM OLD.adjuster_phone       THEN bad := array_append(bad,'adjuster_phone'); END IF;\n  IF NEW.adjuster_email       IS DISTINCT FROM OLD.adjuster_email       THEN bad := array_append(bad,'adjuster_email'); END IF;\n  IF NEW.work_auth_signed     IS DISTINCT FROM OLD.work_auth_signed     THEN bad := array_append(bad,'work_auth_signed'); END IF;\n  IF NEW.docs_complete        IS DISTINCT FROM OLD.docs_complete        THEN bad := array_append(bad,'docs_complete'); END IF;\n  IF NEW.notes                IS DISTINCT FROM OLD.notes                THEN bad := array_append(bad,'notes'); END IF;\n  IF NEW.special_instructions IS DISTINCT FROM OLD.special_instructions THEN bad := array_append(bad,'special_instructions'); END IF;\n  IF NEW.pm_notes             IS DISTINCT FROM OLD.pm_notes             THEN bad := array_append(bad,'pm_notes'); END IF;\n  IF NEW.created_by           IS DISTINCT FROM OLD.created_by           THEN bad := array_append(bad,'created_by'); END IF;\n  IF NEW.created_at           IS DISTINCT FROM OLD.created_at           THEN bad := array_append(bad,'created_at'); END IF;\n  IF NEW.manager_approved_at  IS DISTINCT FROM OLD.manager_approved_at  THEN bad := array_append(bad,'manager_approved_at'); END IF;\n  IF NEW.manager_approved_by  IS DISTINCT FROM OLD.manager_approved_by  THEN bad := array_append(bad,'manager_approved_by'); END IF;\n  IF NEW.archived_at          IS DISTINCT FROM OLD.archived_at          THEN bad := array_append(bad,'archived_at'); END IF;\n  IF NEW.source_job_request_id IS DISTINCT FROM OLD.source_job_request_id THEN bad := array_append(bad,'source_job_request_id'); END IF;\n  IF NEW.source_signed_agreement_id IS DISTINCT FROM OLD.source_signed_agreement_id THEN bad := array_append(bad,'source_signed_agreement_id'); END IF;\n  IF NEW.claim_payment_status IS DISTINCT FROM OLD.claim_payment_status THEN bad := array_append(bad,'claim_payment_status'); END IF;\n  IF NEW.claim_payment_status_v2 IS DISTINCT FROM OLD.claim_payment_status_v2 THEN bad := array_append(bad,'claim_payment_status_v2'); END IF;\n  IF NEW.claim_payment_status_v2_updated_at IS DISTINCT FROM OLD.claim_payment_status_v2_updated_at THEN bad := array_append(bad,'claim_payment_status_v2_updated_at'); END IF;\n  IF NEW.tarping_invoice_id   IS DISTINCT FROM OLD.tarping_invoice_id   THEN bad := array_append(bad,'tarping_invoice_id'); END IF;\n  IF NEW.invoice_sent_at      IS DISTINCT FROM OLD.invoice_sent_at      THEN bad := array_append(bad,'invoice_sent_at'); END IF;\n  IF NEW.submitted_to_carrier_at IS DISTINCT FROM OLD.submitted_to_carrier_at THEN bad := array_append(bad,'submitted_to_carrier_at'); END IF;\n  IF NEW.check_sent_to_homeowner_at IS DISTINCT FROM OLD.check_sent_to_homeowner_at THEN bad := array_append(bad,'check_sent_to_homeowner_at'); END IF;\n  IF NEW.paid_at              IS DISTINCT FROM OLD.paid_at              THEN bad := array_append(bad,'paid_at'); END IF;\n  IF NEW.claim_payment_notes  IS DISTINCT FROM OLD.claim_payment_notes  THEN bad := array_append(bad,'claim_payment_notes'); END IF;\n  IF NEW.claim_payment_updated_at IS DISTINCT FROM OLD.claim_payment_updated_at THEN bad := array_append(bad,'claim_payment_updated_at'); END IF;\n  IF NEW.claim_payment_updated_by IS DISTINCT FROM OLD.claim_payment_updated_by THEN bad := array_append(bad,'claim_payment_updated_by'); END IF;\n\n  IF array_length(bad, 1) > 0 THEN\n    RAISE EXCEPTION 'crew not authorized to modify field(s): %', array_to_string(bad, ', ')\n      USING ERRCODE = '42501';\n  END IF;\n\n  IF NEW.status IS DISTINCT FROM OLD.status THEN\n    IF NOT (NEW.status = ANY(allowed_status)) THEN\n      RAISE EXCEPTION 'crew cannot set status to %', NEW.status USING ERRCODE = '42501';\n    END IF;\n    IF NOT (\n         (OLD.status = 'dispatched'   AND NEW.status = 'on_site')\n      OR (OLD.status = 'on_site'      AND NEW.status = 'in_progress')\n      OR (OLD.status = 'in_progress'  AND NEW.status = 'crew_completed')\n      OR (OLD.status = 'scheduled'    AND NEW.status = 'on_site')\n    ) THEN\n      RAISE EXCEPTION 'crew status transition % -> % not permitted', OLD.status, NEW.status\n        USING ERRCODE = '42501';\n    END IF;\n  END IF;\n\n  RETURN NEW;\nEND\n$function$\n","identity_arguments":""},{"name":"enforce_pa_rights_before_lor","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_pa_rights_before_lor()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant_type text;\n  v_document_type text;\n  v_claim_id text;\n  v_rights_provided boolean := false;\nBEGIN\n  v_document_type := lower(coalesce(\n    nullif(NEW.variables ->> 'DOCUMENT_TYPE', ''),\n    nullif(NEW.variables ->> 'document_type', ''),\n    ''\n  ));\n\n  IF v_document_type <> 'pa_lor' THEN\n    RETURN NEW;\n  END IF;\n\n  SELECT tenant_type\n  INTO v_tenant_type\n  FROM public.tenants\n  WHERE id = NEW.tenant_id;\n\n  IF coalesce(v_tenant_type, '') <> 'PUBLIC_ADJUSTER_FIRM' THEN\n    RETURN NEW;\n  END IF;\n\n  v_claim_id := coalesce(\n    nullif(NEW.variables ->> 'CLAIM_ID', ''),\n    nullif(NEW.variables ->> 'claim_id', '')\n  );\n\n  IF NEW.tenant_id IS NULL OR NEW.contact_id IS NULL OR v_claim_id IS NULL THEN\n    RAISE EXCEPTION 'PA LOR requires tenant, policyholder, and claim context before sending'\n      USING ERRCODE = '23514';\n  END IF;\n\n  SELECT EXISTS (\n    SELECT 1\n    FROM public.pending_agreements rights\n    WHERE rights.tenant_id = NEW.tenant_id\n      AND rights.contact_id = NEW.contact_id\n      AND coalesce(\n        nullif(rights.variables ->> 'CLAIM_ID', ''),\n        nullif(rights.variables ->> 'claim_id', '')\n      ) = v_claim_id\n      AND lower(coalesce(\n        nullif(rights.variables ->> 'DOCUMENT_TYPE', ''),\n        nullif(rights.variables ->> 'document_type', ''),\n        ''\n      )) = 'pa_statement_of_rights'\n      AND rights.status IN ('sent', 'viewed', 'signed')\n  ) INTO v_rights_provided;\n\n  IF NOT v_rights_provided THEN\n    RAISE EXCEPTION 'Provide the Policyholder Statement of Rights before sending the Letter of Representation'\n      USING ERRCODE = '23514';\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"enforce_task_claim_context","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_task_claim_context()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\ndeclare\n  claim_row public.contact_claims%rowtype;\nbegin\n  if new.claim_id is null then\n    return new;\n  end if;\n\n  select * into claim_row\n  from public.contact_claims\n  where id = new.claim_id;\n\n  if not found then\n    raise exception 'task_claim_not_found';\n  end if;\n\n  if new.tenant_id::text is distinct from claim_row.tenant_org_id::text then\n    raise exception 'task_claim_tenant_mismatch';\n  end if;\n\n  if new.contact_id is null then\n    new.contact_id := claim_row.contact_id;\n  elsif new.contact_id::text is distinct from claim_row.contact_id::text then\n    raise exception 'task_claim_contact_mismatch';\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"enforce_tenant_rebuttal_isolation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_tenant_rebuttal_isolation()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_tenant_type text;\n  v_expected_scope text;\n  v_parent_tenant uuid;\n  v_parent_scope text;\nbegin\n  if new.tenant_org_id is null then\n    if coalesce(new.is_template, false) is not true then\n      new.is_active := false;\n      insert into public.tenant_content_integrity_events(\n        content_table, content_row_id, scope_value, event_type, action_taken, details\n      ) values (\n        'tenant_rebuttals', new.id, new.tenancy_type,\n        'tenantless_non_template', 'quarantined',\n        jsonb_build_object('reason', 'tenantless rebuttal must be an admin template')\n      );\n    end if;\n    return new;\n  end if;\n\n  select tenant_type into v_tenant_type\n  from public.tenants\n  where id = new.tenant_org_id;\n\n  v_expected_scope := public.expected_rebuttal_tenancy_type(v_tenant_type);\n\n  if v_tenant_type is null or v_expected_scope is null or new.tenancy_type is distinct from v_expected_scope then\n    new.is_active := false;\n    new.is_template := false;\n    insert into public.tenant_content_integrity_events(\n      tenant_org_id, content_table, content_row_id, scope_value, event_type, action_taken, details\n    ) values (\n      new.tenant_org_id, 'tenant_rebuttals', new.id, new.tenancy_type,\n      'tenant_scope_mismatch', 'quarantined',\n      jsonb_build_object('tenant_type', v_tenant_type, 'expected_scope', v_expected_scope)\n    );\n    return new;\n  end if;\n\n  new.is_template := false;\n\n  if new.derived_from_template_id is not null then\n    select tenant_org_id, tenancy_type\n      into v_parent_tenant, v_parent_scope\n    from public.tenant_rebuttals\n    where id = new.derived_from_template_id;\n\n    if not found or v_parent_tenant is not null or v_parent_scope is distinct from new.tenancy_type then\n      new.is_active := false;\n      insert into public.tenant_content_integrity_events(\n        tenant_org_id, content_table, content_row_id, scope_value, event_type, action_taken, details\n      ) values (\n        new.tenant_org_id, 'tenant_rebuttals', new.id, new.tenancy_type,\n        'invalid_template_provenance', 'quarantined',\n        jsonb_build_object('derived_from_template_id', new.derived_from_template_id)\n      );\n    end if;\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"enforce_test_account_rules","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enforce_test_account_rules()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user uuid := auth.uid();\n  v_tenant text := COALESCE(NEW.tenant_org_id, OLD.tenant_org_id);\n  v_tenant_uuid uuid;\n  v_can_manage boolean := false;\n  v_can_owner boolean := false;\nBEGIN\n  IF v_user IS NULL THEN\n    RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;\n  END IF;\n\n  BEGIN\n    v_tenant_uuid := v_tenant::uuid;\n  EXCEPTION WHEN others THEN\n    v_tenant_uuid := NULL;\n  END;\n\n  v_can_manage := public.is_manager_or_higher(v_user, v_tenant_uuid) OR public.is_system_admin();\n  v_can_owner  := public.is_tenant_owner(v_user, v_tenant_uuid) OR public.is_system_admin();\n\n  IF TG_OP = 'UPDATE' THEN\n    IF OLD.test_account_static = true THEN\n      IF (NEW.is_test_account IS DISTINCT FROM OLD.is_test_account\n          OR NEW.test_account_static IS DISTINCT FROM OLD.test_account_static)\n         AND NOT v_can_owner THEN\n        INSERT INTO public.test_account_audit (contact_id, tenant_org_id, action, performed_by, reason)\n        VALUES (OLD.id, OLD.tenant_org_id, 'static_attempted_modify', v_user, 'blocked: only owner/godmode can modify static test contact');\n        RAISE EXCEPTION 'Static test contact cannot be modified by this role';\n      END IF;\n    END IF;\n\n    IF NEW.is_test_account IS DISTINCT FROM OLD.is_test_account THEN\n      IF NOT v_can_manage THEN\n        RAISE EXCEPTION 'Only Manager or higher can mark/unmark test accounts';\n      END IF;\n      NEW.test_account_marked_by := v_user;\n      NEW.test_account_marked_at := now();\n      INSERT INTO public.test_account_audit (contact_id, tenant_org_id, action, performed_by, reason)\n      VALUES (NEW.id, NEW.tenant_org_id,\n              CASE WHEN NEW.is_test_account THEN 'marked' ELSE 'unmarked' END,\n              v_user, NEW.test_account_reason);\n    END IF;\n\n  ELSIF TG_OP = 'DELETE' THEN\n    IF OLD.test_account_static = true AND NOT v_can_owner THEN\n      INSERT INTO public.test_account_audit (contact_id, tenant_org_id, action, performed_by, reason)\n      VALUES (OLD.id, OLD.tenant_org_id, 'static_attempted_delete', v_user, 'blocked: only owner/godmode can delete static test contact');\n      RAISE EXCEPTION 'Static test contact cannot be deleted by this role';\n    END IF;\n\n  ELSIF TG_OP = 'INSERT' THEN\n    IF NEW.is_test_account = true AND NOT v_can_manage THEN\n      RAISE EXCEPTION 'Only Manager or higher can create test-account contacts';\n    END IF;\n    IF NEW.is_test_account = true THEN\n      NEW.test_account_marked_by := COALESCE(NEW.test_account_marked_by, v_user);\n      NEW.test_account_marked_at := COALESCE(NEW.test_account_marked_at, now());\n    END IF;\n  END IF;\n\n  RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;\nEND;\n$function$\n","identity_arguments":""},{"name":"enqueue_email","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.enqueue_email(queue_name text, payload jsonb)\n RETURNS bigint\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\nBEGIN\n  RETURN pgmq.send(queue_name, payload);\nEXCEPTION WHEN undefined_table THEN\n  PERFORM pgmq.create(queue_name);\n  RETURN pgmq.send(queue_name, payload);\nEND;\n$function$\n","identity_arguments":"queue_name text, payload jsonb"},{"name":"ensure_academy_onboarding_for_member","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ensure_academy_onboarding_for_member(p_user_id uuid, p_tenant_id uuid, p_enrolled_by uuid DEFAULT NULL::uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_track text;\n  v_course record;\n  v_inserted integer := 0;\n  v_seen integer := 0;\n  v_roles text[] := '{}';\n  v_has_module_contract boolean := false;\nbegin\n  if p_user_id is null or p_tenant_id is null then\n    raise exception 'user_id and tenant_id are required';\n  end if;\n\n  if not exists (\n    select 1 from public.user_tenant_memberships\n    where user_id = p_user_id and tenant_id = p_tenant_id and status = 'active'\n  ) then\n    insert into public.academy_provisioning_events(user_id, tenant_id, event_type, status, details)\n    values (p_user_id, p_tenant_id, 'member_onboarding', 'noop', jsonb_build_object('reason','membership_not_active'));\n    return jsonb_build_object('ok', true, 'status', 'noop', 'reason', 'membership_not_active');\n  end if;\n\n  select coalesce(array_agg(distinct lower(ur.role::text)) filter (where ur.role is not null), '{}')\n    into v_roles\n  from public.user_roles ur\n  where ur.user_id = p_user_id and ur.tenant_id = p_tenant_id;\n\n  if exists (\n    select 1 from public.user_tenant_memberships m\n    where m.user_id=p_user_id and m.tenant_id=p_tenant_id and m.status='active' and m.is_owner=true\n  ) then\n    v_roles := array(select distinct x from unnest(v_roles || array['owner','tenant owner']) x);\n  end if;\n\n  select exists(\n    select 1 from public.academy_tenant_modules atm\n    where atm.tenant_org_id = p_tenant_id::text\n  ) into v_has_module_contract;\n\n  v_track := public.academy_track_for_tenant(p_tenant_id);\n\n  for v_course in\n    select c.id, c.tenant_track, c.required_roles, c.required_module_keys\n    from public.academy_courses c\n    where c.is_published = true\n      and c.review_status = 'active'\n      and c.category = 'onboarding'\n      and c.tenant_org_id in ('00000000-0000-0000-0000-000000000000', p_tenant_id::text)\n      and c.tenant_track in ('universal', v_track)\n      and (\n        cardinality(c.required_roles) = 0\n        or exists (\n          select 1 from unnest(c.required_roles) req\n          where lower(req) = any(v_roles)\n        )\n      )\n      and (\n        cardinality(c.required_module_keys) = 0\n        or not v_has_module_contract\n        or not exists (\n          select 1 from unnest(c.required_module_keys) req\n          where not exists (\n            select 1 from public.academy_tenant_modules atm\n            where atm.tenant_org_id = p_tenant_id::text\n              and atm.enabled = true\n              and lower(atm.module_key) = lower(req)\n          )\n        )\n      )\n    order by case when c.tenant_org_id = p_tenant_id::text then 0 else 1 end,\n             case when c.tenant_track = v_track then 0 else 1 end,\n             c.is_required desc,\n             c.created_at asc\n  loop\n    v_seen := v_seen + 1;\n    insert into public.academy_enrollments(course_id, user_id, enrolled_by, status)\n    values (v_course.id, p_user_id, p_enrolled_by, 'active')\n    on conflict (user_id, course_id) do nothing;\n    if found then\n      v_inserted := v_inserted + 1;\n    end if;\n  end loop;\n\n  if v_seen = 0 then\n    insert into public.academy_provisioning_events(user_id, tenant_id, event_type, status, academy_track, details)\n    values (p_user_id, p_tenant_id, 'member_onboarding', 'failed', v_track,\n      jsonb_build_object('reason','no_matching_published_onboarding_course','roles',v_roles,'module_contract',v_has_module_contract));\n    return jsonb_build_object('ok', false, 'status', 'failed', 'track', v_track, 'reason', 'no_matching_published_onboarding_course', 'roles', v_roles);\n  end if;\n\n  insert into public.academy_provisioning_events(user_id, tenant_id, event_type, status, academy_track, details)\n  values (\n    p_user_id,\n    p_tenant_id,\n    'member_onboarding',\n    case when v_inserted > 0 then 'success' else 'noop' end,\n    v_track,\n    jsonb_build_object('courses_matched', v_seen, 'enrollments_created', v_inserted, 'roles', v_roles, 'module_contract', v_has_module_contract)\n  );\n\n  return jsonb_build_object('ok', true, 'status', case when v_inserted > 0 then 'success' else 'noop' end,\n    'track', v_track, 'courses_matched', v_seen, 'enrollments_created', v_inserted, 'roles', v_roles);\nexception when others then\n  begin\n    insert into public.academy_provisioning_events(user_id, tenant_id, event_type, status, academy_track, details)\n    values (p_user_id, p_tenant_id, 'member_onboarding', 'failed', v_track, jsonb_build_object('error', sqlerrm, 'roles', v_roles));\n  exception when others then\n    null;\n  end;\n  return jsonb_build_object('ok', false, 'status', 'failed', 'track', v_track, 'error', sqlerrm, 'roles', v_roles);\nend;\n$function$\n","identity_arguments":"p_user_id uuid, p_tenant_id uuid, p_enrolled_by uuid"},{"name":"ensure_cafe_menu_item_media_stub","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ensure_cafe_menu_item_media_stub()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nbegin\n  insert into public.cafe_menu_item_media (\n    tenant_org_id, menu_item_id, asset_role, status, image_url, alt_text,\n    creative_brief, generation_prompt, source_references, is_primary, sort_order\n  ) values (\n    new.tenant_org_id,\n    new.id,\n    'primary',\n    case when nullif(trim(coalesce(new.image_url,'')),'') is null then 'brief_ready' else 'ready' end,\n    nullif(trim(coalesce(new.image_url,'')),''),\n    new.name || ' product image',\n    jsonb_build_object(\n      'item_name', new.name,\n      'category', new.category,\n      'menu_section', new.menu_section,\n      'flavor_cues', coalesce(new.tags,'[]'::jsonb),\n      'composition', 'single premium menu-card hero product',\n      'logo_rule', 'Use the tenant-approved logo on visible cup or packaging when applicable',\n      'avoid', jsonb_build_array('invented ingredients','invented text','distorted packaging','AI anatomy artifacts')\n    ),\n    'Create a premium realistic commercial menu image for \"' || new.name || '\". Product truth: ' || coalesce(nullif(trim(new.description),''),'Use only verified menu data and the product name.') || ' Category: ' || coalesce(new.category,'menu item') || '. Use the tenant-approved logo on visible cup or packaging when applicable. Do not invent ingredients or text. Keep the product appetizing, realistic, cleanly composed, and menu-card ready.',\n    jsonb_build_array(jsonb_build_object('type','menu_item','external_item_id',new.external_item_id)),\n    true,\n    0\n  ) on conflict do nothing;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"ensure_default_homeowner_stage_rule","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ensure_default_homeowner_stage_rule(p_tenant_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF EXISTS (\n    SELECT 1 FROM public.pipeline_automation_rules\n    WHERE tenant_org_id = p_tenant_id\n      AND name = 'Homeowner Stage Update (Auto)'\n  ) THEN\n    RETURN;\n  END IF;\n\n  INSERT INTO public.pipeline_automation_rules (\n    tenant_org_id, name, description, is_active,\n    trigger_type, trigger_config, conditions, actions, priority\n  ) VALUES (\n    p_tenant_id,\n    'Homeowner Stage Update (Auto)',\n    'Auto-seeded: notifies the homeowner on every pipeline stage change. Customize copy in Owner → Automations → Stage Messaging.',\n    true,\n    'stage_change',\n    '{}'::jsonb,\n    '[]'::jsonb,\n    '[{\"type\":\"send_homeowner_stage_update\",\"config\":{}}]'::jsonb,\n    10\n  );\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"ensure_mobile_vendor_event_workflow","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ensure_mobile_vendor_event_workflow(p_event_booking_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SET search_path TO 'public', 'pg_temp'\nAS $function$\ndeclare\n  v_tenant text;\nbegin\n  select tenant_org_id into v_tenant from public.event_bookings where id = p_event_booking_id;\n  if v_tenant is null then raise exception 'event booking not found'; end if;\n\n  insert into public.event_workflow_steps\n    (tenant_org_id, event_booking_id, phase, step_key, label, sort_order)\n  values\n    (v_tenant, p_event_booking_id, 'Intake', 'confirm_event_details', 'Confirm date, time, venue, attendance, setup, and contact details', 10),\n    (v_tenant, p_event_booking_id, 'Quote', 'prepare_quote', 'Prepare and approve the event quote', 20),\n    (v_tenant, p_event_booking_id, 'Agreement', 'agreement_signed', 'Send the right event agreement and get it signed', 30),\n    (v_tenant, p_event_booking_id, 'Payment', 'deposit_payment', 'Confirm deposit or required payment', 40),\n    (v_tenant, p_event_booking_id, 'Prep', 'venue_requirements', 'Confirm venue access, power, insurance, setup, and vendor requirements', 50),\n    (v_tenant, p_event_booking_id, 'Prep', 'final_headcount', 'Confirm contracted tickets or service quantity, final attendance, and the bid amount', 60),\n    (v_tenant, p_event_booking_id, 'Prep', 'loadout_ready', 'Complete product, supplies, trailer, equipment, staff, food, water, and fuel loadout', 70),\n    (v_tenant, p_event_booking_id, 'Event Day', 'setup_complete', 'Arrive and complete event setup', 80),\n    (v_tenant, p_event_booking_id, 'Event Day', 'service_complete', 'Complete service and account for unused product and reusable gear', 90),\n    (v_tenant, p_event_booking_id, 'Closeout', 'balance_complete', 'Create or close the final invoice and remaining balance', 100),\n    (v_tenant, p_event_booking_id, 'Follow-Up', 'customer_followup', 'Thank the customer, request a review, and schedule repeat-booking follow-up', 110)\n  on conflict (event_booking_id, step_key) do nothing;\nend;\n$function$\n","identity_arguments":"p_event_booking_id uuid"},{"name":"ensure_tenant_provisioning_foundation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.ensure_tenant_provisioning_foundation(p_tenant_id uuid, p_owner_user_id uuid DEFAULT NULL::uuid, p_owner_role text DEFAULT 'Tenant Owner'::text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_caller uuid := auth.uid();\n  v_uid uuid := coalesce(p_owner_user_id, auth.uid());\n  v_tenant public.tenants%rowtype;\n  v_canonical_type text;\n  v_membership_id uuid;\n  v_enrollment_id uuid;\n  v_track text;\n  v_assignment jsonb;\n  v_authorized boolean := false;\nBEGIN\n  IF p_tenant_id IS NULL THEN RAISE EXCEPTION 'Tenant id is required'; END IF;\n  IF v_caller IS NULL THEN RAISE EXCEPTION 'Authentication required' USING ERRCODE = '42501'; END IF;\n  SELECT * INTO v_tenant FROM public.tenants WHERE id = p_tenant_id;\n  IF NOT FOUND THEN RAISE EXCEPTION 'Tenant not found'; END IF;\n  v_authorized := public.is_system_admin(v_caller)\n    OR public.is_admin_or_higher(v_caller, p_tenant_id)\n    OR (v_tenant.owner_id = v_caller AND coalesce(p_owner_user_id, v_caller) = v_caller);\n  IF NOT v_authorized THEN RAISE EXCEPTION 'Not authorized to provision this tenant' USING ERRCODE = '42501'; END IF;\n  IF p_owner_user_id IS NOT NULL AND p_owner_user_id <> v_caller AND NOT public.is_system_admin(v_caller) THEN\n    RAISE EXCEPTION 'Only platform administrators may provision another user as tenant owner' USING ERRCODE = '42501';\n  END IF;\n  v_canonical_type := public.canonical_tenant_type(v_tenant.tenant_type);\n  IF v_canonical_type IS NULL OR v_canonical_type IS DISTINCT FROM v_tenant.tenant_type THEN\n    RAISE EXCEPTION 'Tenant % has unresolved or noncanonical business type %. Explicit tenant classification is required before provisioning.', p_tenant_id, coalesce(v_tenant.tenant_type, '<missing>') USING ERRCODE = '22023';\n  END IF;\n  IF v_uid IS NULL THEN v_uid := v_tenant.owner_id; END IF;\n  IF v_uid IS NULL THEN RAISE EXCEPTION 'Tenant owner is required before provisioning'; END IF;\n  UPDATE public.tenants SET owner_id = coalesce(owner_id, v_uid), updated_at = now() WHERE id = p_tenant_id;\n  INSERT INTO public.user_tenant_memberships(user_id, tenant_id, role, is_owner, status)\n  VALUES(v_uid, p_tenant_id, p_owner_role, true, 'active')\n  ON CONFLICT (user_id, tenant_id) DO UPDATE SET status='active', is_owner=true, role=coalesce(public.user_tenant_memberships.role, excluded.role), updated_at=now()\n  RETURNING id INTO v_membership_id;\n  INSERT INTO public.user_roles(user_id, tenant_id, role, assigned_by)\n  SELECT v_uid, p_tenant_id, 'Admin', v_caller\n  WHERE NOT EXISTS (SELECT 1 FROM public.user_roles WHERE user_id=v_uid AND tenant_id=p_tenant_id AND role='Admin');\n  v_assignment := public.assign_academy_track(p_tenant_id, 'tenant', v_uid);\n  v_track := coalesce(v_assignment->>'track', public.academy_track_for_tenant(p_tenant_id));\n  INSERT INTO public.academy_enrollments(tenant_id,user_id,academy_track,status,source,metadata)\n  VALUES(p_tenant_id,v_uid,v_track,'active','tenant_provisioning',jsonb_build_object('assigned_by','ensure_tenant_provisioning_foundation'))\n  ON CONFLICT (tenant_id,user_id) DO UPDATE SET academy_track=excluded.academy_track,status='active',updated_at=now(),metadata=public.academy_enrollments.metadata||excluded.metadata\n  RETURNING id INTO v_enrollment_id;\n  INSERT INTO public.tenant_readiness_checks(tenant_id,check_key,status,detail)\n  VALUES(p_tenant_id,'academy','ready',jsonb_build_object('track',v_track,'enrollment_id',v_enrollment_id,'owner_id',v_uid))\n  ON CONFLICT (tenant_id,check_key) DO UPDATE SET status='ready',detail=excluded.detail,updated_at=now();\n  RETURN jsonb_build_object('ok',true,'tenant_id',p_tenant_id,'tenant_type',v_canonical_type,'owner_id',v_uid,'membership_id',v_membership_id,'academy_track',v_track,'academy_enrollment_id',v_enrollment_id);\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_owner_user_id uuid, p_owner_role text"},{"name":"execute_sql","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.execute_sql(p_sql_query text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NOT public.is_system_admin(auth.uid()) THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Admin access required');\n  END IF;\n  EXECUTE p_sql_query;\n  RETURN jsonb_build_object('ok', true, 'message', 'SQL executed successfully');\nEXCEPTION WHEN OTHERS THEN\n  RETURN jsonb_build_object('ok', false, 'error', SQLERRM);\nEND;\n$function$\n","identity_arguments":"p_sql_query text"},{"name":"execute_sql_query","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.execute_sql_query(p_sql_query text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_result jsonb;\nBEGIN\n  IF NOT public.is_system_admin(auth.uid()) THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Admin access required');\n  END IF;\n  EXECUTE 'SELECT jsonb_agg(row_to_json(t.*)) FROM (' || p_sql_query || ') t'\n  INTO v_result;\n  RETURN jsonb_build_object('ok', true, 'data', COALESCE(v_result, '[]'::jsonb));\nEXCEPTION WHEN OTHERS THEN\n  RETURN jsonb_build_object('ok', false, 'error', SQLERRM);\nEND;\n$function$\n","identity_arguments":"p_sql_query text"},{"name":"expected_rebuttal_tenancy_type","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.expected_rebuttal_tenancy_type(p_tenant_type text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  select case upper(coalesce(p_tenant_type, ''))\n    when 'MITIGATION' then 'mitigation'\n    when 'ROOFING_COMPANY' then 'roofing'\n    when 'PUBLIC_ADJUSTER_FIRM' then 'public_adjuster'\n    when 'REALTOR' then 'realtor'\n    else null\n  end\n$function$\n","identity_arguments":"p_tenant_type text"},{"name":"fill_permit_lookup_attempt_attribution","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.fill_permit_lookup_attempt_attribution()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\r\ndeclare\r\n  inferred_tenant uuid;\r\n  tenant_count integer;\r\n  cfg record;\r\n  cfg_count integer;\r\nbegin\r\n  if new.tenant_org_id is null and new.triggered_by is not null then\r\n    select count(distinct uta.tenant_id)\r\n      into tenant_count\r\n    from public.user_tenant_access uta\r\n    where uta.user_id = new.triggered_by\r\n      and coalesce(uta.membership_status, 'active') in ('active', 'accepted')\r\n      and coalesce(uta.has_membership, true) = true;\r\n\r\n    if tenant_count = 1 then\r\n      select uta.tenant_id\r\n        into inferred_tenant\r\n      from public.user_tenant_access uta\r\n      where uta.user_id = new.triggered_by\r\n        and coalesce(uta.membership_status, 'active') in ('active', 'accepted')\r\n        and coalesce(uta.has_membership, true) = true\r\n      limit 1;\r\n\r\n      new.tenant_org_id := inferred_tenant;\r\n    end if;\r\n  end if;\r\n\r\n  if new.tenant_org_id is not null\r\n     and (\r\n       new.searched_source is null or new.searched_source = '' or new.searched_source = 'Unknown'\r\n       or new.searched_jurisdiction is null or new.searched_jurisdiction = '' or new.searched_jurisdiction = 'Unknown'\r\n     ) then\r\n    select count(*)\r\n      into cfg_count\r\n    from public.permit_source_configs psc\r\n    where psc.tenant_org_id = new.tenant_org_id\r\n      and psc.enabled = true;\r\n\r\n    if cfg_count = 1 then\r\n      select psc.source_name, psc.municipality, psc.county, psc.state\r\n        into cfg\r\n      from public.permit_source_configs psc\r\n      where psc.tenant_org_id = new.tenant_org_id\r\n        and psc.enabled = true\r\n      limit 1;\r\n\r\n      if new.searched_source is null or new.searched_source = '' or new.searched_source = 'Unknown' then\r\n        new.searched_source := cfg.source_name;\r\n      end if;\r\n\r\n      if new.searched_jurisdiction is null or new.searched_jurisdiction = '' or new.searched_jurisdiction = 'Unknown' then\r\n        new.searched_jurisdiction := trim(both ', ' from concat_ws(', ', cfg.municipality, cfg.county, cfg.state));\r\n      end if;\r\n    end if;\r\n  end if;\r\n\r\n  return new;\r\nend;\r\n$function$\n","identity_arguments":""},{"name":"flag_roof_related_permit","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.flag_roof_related_permit()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nDECLARE combined TEXT;\nBEGIN\n  combined := lower(coalesce(NEW.permit_type,'') || ' ' ||\n                    coalesce(NEW.description,'') || ' ' ||\n                    coalesce(NEW.notes,''));\n  NEW.is_roof_related := (combined ~ '(roof|reroof|re-roof|shingle|tile re|tile-re|tarp|tarping)');\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"force_end_call_session","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.force_end_call_session(_session_id uuid, _reason text)\n RETURNS active_call_sessions\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  s public.active_call_sessions;\nBEGIN\n  SELECT * INTO s FROM public.active_call_sessions WHERE id = _session_id;\n  IF s.id IS NULL THEN\n    RAISE EXCEPTION 'Session not found';\n  END IF;\n  IF NOT public.is_manager_or_higher(auth.uid(), s.tenant_org_id::uuid) THEN\n    RAISE EXCEPTION 'Not authorized';\n  END IF;\n\n  UPDATE public.active_call_sessions\n     SET status = 'ended',\n         ended_at = now(),\n         force_ended_by_user_id = auth.uid(),\n         force_ended_reason = COALESCE(NULLIF(trim(_reason), ''), 'Force-ended by manager'),\n         force_ended_at = now()\n   WHERE id = _session_id\n   RETURNING * INTO s;\n\n  RETURN s;\nEND;\n$function$\n","identity_arguments":"_session_id uuid, _reason text"},{"name":"generate_lawn_service_visits","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.generate_lawn_service_visits(p_tenant_id uuid, p_start_date date DEFAULT CURRENT_DATE, p_days integer DEFAULT 42)\n RETURNS integer\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nDECLARE inserted_count integer := 0;\nBEGIN\n  INSERT INTO public.lawn_service_visits (\n    tenant_id, service_plan_id, contact_id, service_date, stop_order,\n    status, assigned_crew_id, metadata\n  )\n  SELECT\n    plan.tenant_id,\n    plan.id,\n    plan.contact_id,\n    day::date,\n    row_number() OVER (PARTITION BY day ORDER BY plan.route_day, plan.created_at, plan.contact_id)::integer,\n    'scheduled',\n    plan.assigned_crew_id,\n    jsonb_build_object(\n      'generated_by', 'recurring_service_engine_v2',\n      'cadence', plan.cadence,\n      'anchor_date', coalesce(plan.next_service_date, plan.created_at::date)\n    )\n  FROM public.lawn_service_plans plan\n  CROSS JOIN LATERAL generate_series(\n    p_start_date,\n    p_start_date + greatest(0, least(p_days, 120)),\n    interval '1 day'\n  ) day\n  WHERE plan.tenant_id = p_tenant_id\n    AND plan.status = 'active'\n    AND plan.route_day IS NOT NULL\n    AND (plan.pause_until IS NULL OR day::date > plan.pause_until)\n    AND trim(to_char(day, 'Day')) = plan.route_day\n    AND day::date >= coalesce(plan.next_service_date, plan.created_at::date)\n    AND CASE plan.cadence\n      WHEN 'weekly' THEN mod(day::date - coalesce(plan.next_service_date, plan.created_at::date), 7) = 0\n      WHEN 'biweekly' THEN mod(day::date - coalesce(plan.next_service_date, plan.created_at::date), 14) = 0\n      WHEN 'monthly' THEN extract(day from day::date) <= 7\n      WHEN 'one_time' THEN day::date = coalesce(plan.next_service_date, plan.created_at::date)\n      ELSE false\n    END\n  ON CONFLICT (tenant_id, contact_id, service_date) DO NOTHING;\n\n  GET DIAGNOSTICS inserted_count = ROW_COUNT;\n\n  UPDATE public.lawn_service_plans plan\n  SET next_service_date = (\n    SELECT min(v.service_date)\n    FROM public.lawn_service_visits v\n    WHERE v.tenant_id = plan.tenant_id\n      AND v.service_plan_id = plan.id\n      AND v.service_date >= current_date\n      AND v.status IN ('scheduled','in_progress','rescheduled')\n  )\n  WHERE plan.tenant_id = p_tenant_id\n    AND EXISTS (\n      SELECT 1\n      FROM public.lawn_service_visits v\n      WHERE v.tenant_id = plan.tenant_id\n        AND v.service_plan_id = plan.id\n        AND v.service_date >= current_date\n        AND v.status IN ('scheduled','in_progress','rescheduled')\n    );\n\n  RETURN inserted_count;\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_start_date date, p_days integer"},{"name":"generate_portal_token","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.generate_portal_token()\n RETURNS text\n LANGUAGE plpgsql\n SET search_path TO 'pg_catalog', 'pg_temp'\nAS $function$\nDECLARE\n  alphabet text := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n  result text := '';\n  i int;\nBEGIN\n  FOR i IN 1..24 LOOP\n    result := result || substr(alphabet, 1 + floor(random() * length(alphabet))::int, 1);\n  END LOOP;\n  RETURN result;\nEND;\n$function$\n","identity_arguments":""},{"name":"get_active_call_floor","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_active_call_floor(p_tenant_org_id text)\n RETURNS TABLE(session_id uuid, rep_id uuid, rep_name text, lead_id uuid, lead_name text, phone_number text, status text, started_at timestamp with time zone, parent_call_sid text, homeowner_call_sid text)\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT\n    s.id AS session_id,\n    s.rep_id,\n    p.name AS rep_name,\n    s.lead_id,\n    COALESCE(NULLIF(TRIM(CONCAT(uc.first_name, ' ', uc.last_name)), ''), l.name, 'Unknown') AS lead_name,\n    s.phone_number,\n    s.status,\n    s.started_at,\n    s.parent_call_sid,\n    s.homeowner_call_sid\n  FROM public.active_call_sessions s\n  LEFT JOIN public.profiles p ON p.id = s.rep_id\n  LEFT JOIN public.leads l ON l.id = s.lead_id\n  LEFT JOIN public.unified_contacts uc ON uc.id = s.lead_id\n  WHERE s.tenant_org_id = p_tenant_org_id\n    AND s.ended_at IS NULL\n    AND s.status NOT IN ('ended','failed','completed','no-answer','busy')\n    AND (\n      is_admin_or_higher(auth.uid(), p_tenant_org_id::uuid)\n      OR is_system_admin()\n    )\n  ORDER BY s.started_at DESC;\n$function$\n","identity_arguments":"p_tenant_org_id text"},{"name":"get_all_tables","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_all_tables()\n RETURNS TABLE(table_name text)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\nbegin\n  perform public.require_platform_operator();\n  return query\n    select t.tablename::text\n    from pg_catalog.pg_tables t\n    where t.schemaname = 'public'\n    order by t.tablename;\nend;\n$function$\n","identity_arguments":""},{"name":"get_contact_claim_payment_history","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_contact_claim_payment_history(_claim_id uuid)\n RETURNS TABLE(id uuid, claim_id uuid, from_status claim_payment_lifecycle_v4, to_status claim_payment_lifecycle_v4, changed_by uuid, changed_at timestamp with time zone, note text, source text)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _uid uuid := auth.uid();\n  _tenant text;\n  _allowed boolean;\nBEGIN\n  IF _uid IS NULL THEN\n    RAISE EXCEPTION 'unauthenticated' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT cc.tenant_org_id INTO _tenant\n  FROM public.contact_claims cc\n  WHERE cc.id = _claim_id;\n\n  IF _tenant IS NULL THEN\n    RAISE EXCEPTION 'claim not found' USING ERRCODE = 'P0002';\n  END IF;\n\n  SELECT\n    public.is_system_admin(_uid)\n    OR public.is_manager_or_higher(_uid, _tenant::uuid)\n    OR EXISTS (\n      SELECT 1 FROM public.user_roles ur\n      WHERE ur.user_id = _uid\n        AND ur.tenant_id = _tenant::uuid\n        AND ur.role = 'PM'::public.app_role\n    )\n  INTO _allowed;\n\n  IF NOT _allowed THEN\n    RAISE EXCEPTION 'forbidden: claim/payment history not visible to your role'\n      USING ERRCODE = '42501';\n  END IF;\n\n  RETURN QUERY\n  SELECT h.id, h.claim_id, h.from_status, h.to_status, h.changed_by, h.changed_at, h.note, h.source\n  FROM public.claim_payment_status_history h\n  WHERE h.claim_id = _claim_id\n  ORDER BY h.changed_at DESC;\nEND;\n$function$\n","identity_arguments":"_claim_id uuid"},{"name":"get_contact_claim_payment_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_contact_claim_payment_status(_claim_id uuid)\n RETURNS TABLE(id uuid, claim_payment_status claim_payment_lifecycle_v4, claim_payment_status_updated_at timestamp with time zone, claim_payment_status_updated_by uuid)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _uid uuid := auth.uid();\n  _tenant text;\n  _allowed boolean;\nBEGIN\n  IF _uid IS NULL THEN\n    RAISE EXCEPTION 'unauthenticated' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT cc.tenant_org_id INTO _tenant\n  FROM public.contact_claims cc\n  WHERE cc.id = _claim_id;\n\n  IF _tenant IS NULL THEN\n    RAISE EXCEPTION 'claim not found' USING ERRCODE = 'P0002';\n  END IF;\n\n  SELECT\n    public.is_system_admin(_uid)\n    OR public.is_manager_or_higher(_uid, _tenant::uuid)\n    OR EXISTS (\n      SELECT 1 FROM public.user_roles ur\n      WHERE ur.user_id = _uid\n        AND ur.tenant_id = _tenant::uuid\n        AND ur.role = 'PM'::public.app_role\n    )\n  INTO _allowed;\n\n  IF NOT _allowed THEN\n    RAISE EXCEPTION 'forbidden: claim/payment status not visible to your role'\n      USING ERRCODE = '42501';\n  END IF;\n\n  RETURN QUERY\n  SELECT cc.id,\n         cc.claim_payment_status,\n         cc.claim_payment_status_updated_at,\n         cc.claim_payment_status_updated_by\n  FROM public.contact_claims cc\n  WHERE cc.id = _claim_id;\nEND;\n$function$\n","identity_arguments":"_claim_id uuid"},{"name":"get_contact_compliance_bypass","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_contact_compliance_bypass(_tenant_org_id text, _contact_id uuid)\n RETURNS TABLE(active boolean, checked_at timestamp with time zone, checked_by uuid, reason text, phone_number text, raw_response jsonb)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user uuid := auth.uid();\n  v_tenant_uuid uuid;\n  v_can_bypass boolean := false;\nBEGIN\n  IF v_user IS NULL OR _tenant_org_id IS NULL OR _contact_id IS NULL THEN\n    RETURN QUERY SELECT false, NULL::timestamptz, NULL::uuid, NULL::text, NULL::text, NULL::jsonb;\n    RETURN;\n  END IF;\n\n  BEGIN\n    v_tenant_uuid := _tenant_org_id::uuid;\n  EXCEPTION WHEN others THEN\n    v_tenant_uuid := NULL;\n  END;\n\n  v_can_bypass := public.is_system_admin(v_user)\n    OR (v_tenant_uuid IS NOT NULL AND public.is_admin_or_higher(v_user, v_tenant_uuid));\n\n  IF NOT v_can_bypass THEN\n    RETURN QUERY SELECT false, NULL::timestamptz, NULL::uuid, NULL::text, NULL::text, NULL::jsonb;\n    RETURN;\n  END IF;\n\n  IF NOT EXISTS (\n    SELECT 1\n    FROM public.unified_contacts uc\n    WHERE uc.id = _contact_id\n      AND uc.tenant_org_id = _tenant_org_id\n      AND uc.is_test_account = true\n  ) THEN\n    RETURN QUERY SELECT false, NULL::timestamptz, NULL::uuid, NULL::text, NULL::text, NULL::jsonb;\n    RETURN;\n  END IF;\n\n  RETURN QUERY\n  SELECT\n    COALESCE(ce.result = 'bypass_enabled', false) AS active,\n    ce.checked_at,\n    ce.checked_by,\n    ce.reason,\n    ce.phone_number,\n    ce.raw_response\n  FROM public.communication_compliance_events ce\n  WHERE ce.tenant_org_id = _tenant_org_id\n    AND ce.lead_id = _contact_id::text\n    AND ce.check_type = 'owner_bypass'\n  ORDER BY ce.checked_at DESC\n  LIMIT 1;\n\n  IF NOT FOUND THEN\n    RETURN QUERY SELECT false, NULL::timestamptz, NULL::uuid, NULL::text, NULL::text, NULL::jsonb;\n  END IF;\nEND;\n$function$\n","identity_arguments":"_tenant_org_id text, _contact_id uuid"},{"name":"get_doors_in_territory","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_doors_in_territory(p_territory_id uuid)\n RETURNS SETOF door_objects\n LANGUAGE plpgsql\n STABLE\n SET search_path TO 'public'\nAS $function$\nDECLARE v_polygon JSONB;\nBEGIN\n  SELECT polygon_geojson INTO v_polygon FROM territories WHERE id = p_territory_id;\n  RETURN QUERY SELECT d.* FROM door_objects d\n  WHERE d.territory_id = p_territory_id OR ST_Contains(ST_GeomFromGeoJSON(v_polygon::text), ST_MakePoint(d.lng, d.lat));\nEND;\n$function$\n","identity_arguments":"p_territory_id uuid"},{"name":"get_doors_near_point","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_doors_near_point(p_lat double precision, p_lng double precision, p_radius_miles double precision, p_tenant_org_id text)\n RETURNS SETOF door_objects\n LANGUAGE sql\n STABLE\n SET search_path TO 'public', 'extensions'\nAS $function$\n  SELECT * FROM door_objects WHERE tenant_org_id = p_tenant_org_id\n    AND extensions.earth_distance(extensions.ll_to_earth(lat, lng), extensions.ll_to_earth(p_lat, p_lng)) <= (p_radius_miles * 1609.34)\n  ORDER BY extensions.earth_distance(extensions.ll_to_earth(lat, lng), extensions.ll_to_earth(p_lat, p_lng));\n$function$\n","identity_arguments":"p_lat double precision, p_lng double precision, p_radius_miles double precision, p_tenant_org_id text"},{"name":"get_jobs_package_readiness","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_jobs_package_readiness(_job_id uuid)\n RETURNS TABLE(job_id uuid, tenant_id uuid, contact_claim_id uuid, job_status text, verified_at timestamp with time zone, work_auth_signed boolean, photos_uploaded boolean, docs_complete boolean, invoice_present boolean, carrier_present boolean, policy_present boolean, claim_present boolean, contact_present boolean, package_ready boolean, claim_payment_status claim_payment_lifecycle_v4)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_tenant uuid;\n  v_can_view boolean;\nBEGIN\n  IF auth.uid() IS NULL THEN\n    RAISE EXCEPTION 'unauthenticated' USING ERRCODE='42501';\n  END IF;\n  SELECT j.tenant_id INTO v_tenant FROM public.jobs j WHERE j.id = _job_id;\n  IF v_tenant IS NULL THEN RAISE EXCEPTION 'job not found' USING ERRCODE='02000'; END IF;\n  IF NOT public.is_tenant_member(auth.uid(), v_tenant) AND NOT public.is_system_admin(auth.uid()) THEN\n    RAISE EXCEPTION 'cross-tenant job access denied' USING ERRCODE='42501';\n  END IF;\n  v_can_view := public._can_view_claim_payment_status(v_tenant);\n  RETURN QUERY\n    SELECT\n      j.id, j.tenant_id, j.contact_claim_id, j.status::text, j.verified_at,\n      j.work_auth_signed, j.photos_uploaded, j.docs_complete,\n      (j.tarping_invoice_id IS NOT NULL),\n      (COALESCE(j.carrier_name,'')<>''),\n      (COALESCE(j.policy_number,'')<>''),\n      (COALESCE(j.claim_number,'')<>''),\n      (COALESCE(j.property_address,'')<>'' AND COALESCE(j.customer_name,'')<>''),\n      (j.work_auth_signed AND j.photos_uploaded AND j.docs_complete\n        AND j.verified_at IS NOT NULL AND j.tarping_invoice_id IS NOT NULL\n        AND COALESCE(j.carrier_name,'')<>'' AND COALESCE(j.policy_number,'')<>''\n        AND COALESCE(j.claim_number,'')<>''),\n      CASE WHEN v_can_view AND j.contact_claim_id IS NOT NULL\n        THEN (SELECT cc.claim_payment_status FROM public.contact_claims cc WHERE cc.id = j.contact_claim_id)\n        ELSE NULL\n      END\n    FROM public.jobs j WHERE j.id = _job_id;\nEND;\n$function$\n","identity_arguments":"_job_id uuid"},{"name":"get_knocklaunch_platform_zoho_mail_credentials","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_knocklaunch_platform_zoho_mail_credentials()\n RETURNS TABLE(client_id text, client_secret text)\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\n  select\n    max(case when name = 'knocklaunch_platform_zoho_mail_client_id' then decrypted_secret end)::text as client_id,\n    max(case when name = 'knocklaunch_platform_zoho_mail_client_secret' then decrypted_secret end)::text as client_secret\n  from vault.decrypted_secrets\n  where name in ('knocklaunch_platform_zoho_mail_client_id', 'knocklaunch_platform_zoho_mail_client_secret');\n$function$\n","identity_arguments":""},{"name":"get_last_dnc_scrub","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_last_dnc_scrub(_tenant_id uuid DEFAULT NULL::uuid)\n RETURNS TABLE(last_run_at timestamp with time zone, days_since integer, is_overdue boolean, is_warning boolean, last_batch_id text, last_run_id uuid)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF _tenant_id IS NULL THEN\n    IF coalesce(auth.role(), '') <> 'service_role'\n       AND (auth.uid() IS NULL OR NOT coalesce(public.is_system_admin(auth.uid()), false)) THEN\n      RAISE EXCEPTION 'platform DNC status access denied' USING ERRCODE = '42501';\n    END IF;\n  ELSIF coalesce(auth.role(), '') <> 'service_role'\n        AND (\n          auth.uid() IS NULL\n          OR (\n            NOT coalesce(public.is_system_admin(auth.uid()), false)\n            AND NOT coalesce(public.is_tenant_member(auth.uid(), _tenant_id), false)\n          )\n        ) THEN\n    RAISE EXCEPTION 'tenant DNC status access denied' USING ERRCODE = '42501';\n  END IF;\n\n  RETURN QUERY\n  WITH latest AS (\n    SELECT id, batch_id, created_at\n    FROM public.dnc_scrub_runs\n    WHERE (_tenant_id IS NULL AND scope = 'platform')\n       OR (_tenant_id IS NOT NULL AND (tenant_id = _tenant_id OR scope = 'platform'))\n    ORDER BY created_at DESC\n    LIMIT 1\n  )\n  SELECT l.created_at,\n         coalesce(extract(day from (now() - l.created_at))::integer, 999),\n         coalesce(extract(day from (now() - l.created_at))::integer, 999) >= 31,\n         coalesce(extract(day from (now() - l.created_at))::integer, 999) BETWEEN 25 AND 30,\n         l.batch_id, l.id\n  FROM latest l\n  UNION ALL\n  SELECT NULL::timestamptz, 999, true, false, NULL::text, NULL::uuid\n  WHERE NOT EXISTS (SELECT 1 FROM latest)\n  LIMIT 1;\nEND;\n$function$\n","identity_arguments":"_tenant_id uuid"},{"name":"get_lead_last_call","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_lead_last_call(p_tenant_org_id text, p_lead_id uuid)\n RETURNS TABLE(last_call_at timestamp with time zone, last_outcome text, last_disposition text)\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT ce.created_at, ce.outcome, ce.disposition\n  FROM public.communication_events ce\n  WHERE public.is_tenant_member(p_tenant_org_id)\n    AND ce.tenant_org_id = p_tenant_org_id\n    AND ce.lead_id = p_lead_id\n    AND ce.event_type IN ('call_completed','call_ended_by_rep','outbound_call','call_no_answer','call_busy')\n  ORDER BY ce.created_at DESC\n  LIMIT 1;\n$function$\n","identity_arguments":"p_tenant_org_id text, p_lead_id uuid"},{"name":"get_lead_timeline","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_lead_timeline(_lead_id text, _limit integer DEFAULT 200)\n RETURNS SETOF lead_timeline\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT t.*\n  FROM public.lead_timeline t\n  WHERE t.lead_id = _lead_id\n    AND t.tenant_org_id IS NOT NULL\n    AND public.is_tenant_member(auth.uid(), t.tenant_org_id)\n  ORDER BY t.occurred_at DESC\n  LIMIT _limit\n$function$\n","identity_arguments":"_lead_id text, _limit integer"},{"name":"get_my_onboarding_context","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_my_onboarding_context(p_session_id uuid DEFAULT NULL::uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_uid uuid := auth.uid();\n  s public.onboarding_sessions%rowtype;\n  v_research jsonb := '[]'::jsonb;\n  v_next text;\nbegin\n  if v_uid is null then raise exception 'Authentication required' using errcode='42501'; end if;\n\n  if p_session_id is null then\n    select * into s\n    from public.onboarding_sessions\n    where owner_user_id=v_uid\n    order by updated_at desc\n    limit 1;\n  else\n    select * into s\n    from public.onboarding_sessions\n    where id=p_session_id and (owner_user_id=v_uid or public.is_system_admin(v_uid));\n  end if;\n\n  if not found then\n    return jsonb_build_object('ok',true,'session',null,'research','[]'::jsonb,'next_step','start');\n  end if;\n\n  select coalesce(jsonb_agg(jsonb_build_object(\n      'type',t.research_type,\n      'jurisdiction',t.jurisdiction,\n      'status',t.status,\n      'result',t.result,\n      'source_url',t.source_url,\n      'verified_at',t.verified_at,\n      'message',t.last_error\n    ) order by t.created_at),'[]'::jsonb)\n  into v_research\n  from public.onboarding_research_tasks t\n  where t.session_id=s.id;\n\n  v_next := case\n    when s.status in ('draft','intake','needs_input') then 'answer_unresolved'\n    when s.status in ('researching','validating') then 'reviewing'\n    when s.status='ready_to_provision' then 'review_and_provision'\n    when s.status='provisioning' then 'provisioning'\n    when s.status in ('ready','live') then 'enter_knocklaunch'\n    when s.status='failed' then 'retry'\n    else 'continue'\n  end;\n\n  return jsonb_build_object(\n    'ok',true,\n    'session',to_jsonb(s),\n    'review',jsonb_build_object(\n      'company_name',s.company_name,\n      'business_type',s.canonical_tenant_type,\n      'service_lines',s.service_lines,\n      'operating_states',to_jsonb(s.operating_states),\n      'service_area',s.service_area,\n      'team_size',s.team_size,\n      'blueprint',s.derived_blueprint\n    ),\n    'research',v_research,\n    'unresolved',coalesce(s.readiness->'missing','[]'::jsonb),\n    'next_step',v_next\n  );\nend;\n$function$\n","identity_arguments":"p_session_id uuid"},{"name":"get_next_lead","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_next_lead(p_user_id uuid, p_tenant_id uuid)\n RETURNS TABLE(lead_id text, name text, phone text, email text, address text, city text, state text, zip text, status text, priority text, source text, assigned_to text, notes text)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_caller uuid := auth.uid();\n  v_user_id_text text := p_user_id::text;\n  v_tenant_id_text text := p_tenant_id::text;\n  v_user_email text;\n  v_system_admin boolean := false;\nBEGIN\n  IF v_caller IS NULL THEN\n    RAISE EXCEPTION 'not_authenticated' USING ERRCODE = '42501';\n  END IF;\n  IF p_user_id IS NULL OR p_tenant_id IS NULL THEN\n    RAISE EXCEPTION 'user_and_tenant_required' USING ERRCODE = '22023';\n  END IF;\n  IF NOT public.is_tenant_member(v_caller, p_tenant_id) THEN\n    RAISE EXCEPTION 'tenant_access_denied' USING ERRCODE = '42501';\n  END IF;\n  IF v_caller <> p_user_id AND NOT public.is_manager_or_higher(v_caller, p_tenant_id) THEN\n    RAISE EXCEPTION 'user_scope_denied' USING ERRCODE = '42501';\n  END IF;\n\n  v_system_admin := public.is_system_admin(v_caller);\n  SELECT p.email INTO v_user_email FROM public.profiles p WHERE p.id = p_user_id LIMIT 1;\n\n  RETURN QUERY\n  SELECT\n    ld.lead_id::text,\n    ld.name,\n    ld.phone,\n    ld.email,\n    ld.address,\n    ld.city,\n    ld.state,\n    ld.zip,\n    ld.status,\n    ld.priority,\n    ld.source,\n    ld.assigned_to,\n    ld.notes\n  FROM public.lead_deck ld\n  WHERE ld.deleted_at IS NULL\n    AND (ld.status IS NULL OR ld.status NOT IN ('Completed','Closed','Lost'))\n    AND (\n      (v_system_admin AND ld.tenant_org_id IS NULL AND (ld.assigned_to IS NULL OR ld.assigned_to = ''))\n      OR\n      (\n        ld.tenant_org_id = v_tenant_id_text\n        AND (\n          ld.assigned_to IS NULL\n          OR ld.assigned_to = ''\n          OR ld.assigned_to = v_user_id_text\n          OR lower(ld.assigned_to) = lower(v_user_email)\n        )\n      )\n    )\n  ORDER BY\n    CASE WHEN ld.tenant_org_id = v_tenant_id_text AND (ld.assigned_to IS NULL OR ld.assigned_to = '') THEN 0 ELSE 1 END,\n    random()\n  LIMIT 1;\nEND;\n$function$\n","identity_arguments":"p_user_id uuid, p_tenant_id uuid"},{"name":"get_owner_dashboard_stats","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_owner_dashboard_stats(p_tenant_id text)\n RETURNS jsonb\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT jsonb_build_object(\n    'total', COUNT(*),\n    'missing_address', COUNT(*) FILTER (WHERE address IS NULL OR trim(address) = ''),\n    'missing_city', COUNT(*) FILTER (WHERE city IS NULL OR trim(city) = ''),\n    'missing_zip', COUNT(*) FILTER (WHERE zip IS NULL OR trim(zip) = ''),\n    'missing_phone', COUNT(*) FILTER (WHERE phone IS NULL OR trim(phone) = ''),\n    'missing_email', COUNT(*) FILTER (WHERE email IS NULL OR trim(email) = ''),\n    'with_address', COUNT(*) FILTER (WHERE address IS NOT NULL AND trim(address) <> ''),\n    'with_property_data', COUNT(*) FILTER (WHERE property_owner_name IS NOT NULL OR property_square_feet IS NOT NULL),\n    'with_roof_year', COUNT(*) FILTER (WHERE property_data->>'lastRoofPermitYear' IS NOT NULL OR property_data->>'roofPermitYear' IS NOT NULL OR property_data->>'last_roof_permit_year' IS NOT NULL),\n    'needs_enrichment', COUNT(*) FILTER (WHERE address IS NOT NULL AND trim(address) <> '' AND property_owner_name IS NULL AND property_square_feet IS NULL)\n  )\n  FROM public.unified_contacts\n  WHERE public.is_tenant_member(p_tenant_id)\n    AND tenant_org_id = p_tenant_id\n    AND deleted_at IS NULL;\n$function$\n","identity_arguments":"p_tenant_id text"},{"name":"get_owner_setup_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_owner_setup_status()\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant_id UUID; v_google BOOLEAN := FALSE; v_roles_done BOOLEAN := FALSE; v_team_done BOOLEAN := FALSE; v_scripts_done BOOLEAN := FALSE; v_zones_done BOOLEAN := FALSE; v_tenant_type TEXT; v_canonical_type TEXT; v_result JSONB;\nBEGIN\n  SELECT tenant_org_id INTO v_tenant_id FROM public.profiles WHERE id = auth.uid();\n  SELECT EXISTS(SELECT 1 FROM public.google_integrations WHERE user_id = auth.uid() AND status = 'connected') INTO v_google;\n  SELECT EXISTS(SELECT 1 FROM public.user_roles WHERE tenant_id = v_tenant_id AND role NOT IN ('GodMode','Admin')) INTO v_roles_done;\n  SELECT (COUNT(*) > 1) INTO v_team_done FROM public.profiles p WHERE p.tenant_org_id = v_tenant_id AND p.active = true;\n  SELECT t.tenant_type INTO v_tenant_type FROM public.tenant_organizations t WHERE t.id = v_tenant_id;\n  v_canonical_type := public.canonical_tenant_type(v_tenant_type);\n  IF v_canonical_type IS NOT NULL THEN\n    SELECT EXISTS(SELECT 1 FROM public.rebuttal_scripts rs WHERE rs.tenant_id = v_tenant_id AND rs.script_type = ('workflow_flowcards_' || v_canonical_type) AND rs.active = true) INTO v_scripts_done;\n  ELSE v_scripts_done := FALSE; END IF;\n  SELECT EXISTS(SELECT 1 FROM public.sales_zones sz WHERE sz.tenant_id = v_tenant_id AND sz.active = true) INTO v_zones_done;\n  v_result := jsonb_build_object('google_connected', v_google,'roles_configured', v_roles_done,'team_added', v_team_done,'workflow_scripts', v_scripts_done,'sales_zones', v_zones_done,'all_complete', (v_google AND v_roles_done AND v_team_done AND v_scripts_done AND v_zones_done));\n  RETURN v_result;\nEND;\n$function$\n","identity_arguments":""},{"name":"get_owner_setup_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_owner_setup_status(p_tenant_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant_type text;\n  v_team_done boolean;\n  v_areas_done boolean;\n  v_pipelines_done boolean;\n  v_scripts_done boolean;\n  v_import_done boolean;\n  v_storms_done boolean;\nBEGIN\n  IF NOT public.is_tenant_member(p_tenant_id) AND NOT public.is_system_admin() THEN\n    RAISE EXCEPTION 'Access denied to tenant %', p_tenant_id;\n  END IF;\n\n  SELECT tenant_type INTO v_tenant_type\n  FROM public.tenant_organizations\n  WHERE id = p_tenant_id;\n\n  v_team_done := (\n    SELECT COUNT(*) > 1 FROM public.user_roles WHERE tenant_id = p_tenant_id\n  );\n\n  v_areas_done := (\n    SELECT COUNT(*) > 0 FROM public.tenant_service_areas WHERE tenant_org_id = p_tenant_id\n  );\n\n  v_pipelines_done := (\n    SELECT COUNT(*) > 3 FROM public.pipeline_stages\n    WHERE tenant_org_id = p_tenant_id AND is_active = true\n  );\n\n  v_scripts_done := (\n    SELECT EXISTS (\n      SELECT 1 FROM public.site_config\n      WHERE config_key = 'workflow_flowcards_' || COALESCE(v_tenant_type, 'MITIGATION')\n        AND tenant_org_id = p_tenant_id\n        AND config_value IS NOT NULL\n    )\n  );\n\n  v_import_done := (\n    SELECT COUNT(*) > 0 FROM public.unified_contacts\n    WHERE tenant_org_id = p_tenant_id AND deleted_at IS NULL\n  );\n\n  v_storms_done := (\n    SELECT COUNT(*) > 0 FROM public.storm_events WHERE tenant_org_id = p_tenant_id\n  );\n\n  RETURN jsonb_build_object(\n    'team', v_team_done,\n    'service-areas', v_areas_done,\n    'pipelines', v_pipelines_done,\n    'scripts', v_scripts_done,\n    'import', v_import_done,\n    'storms', v_storms_done\n  );\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"get_partner_tenant_ids","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_partner_tenant_ids()\n RETURNS SETOF uuid\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT DISTINCT uc.tenant_org_id::uuid\n  FROM public.contact_links cl\n  JOIN public.unified_contacts uc ON cl.contact_id = uc.id\n  WHERE cl.link_group_id IN (\n    SELECT DISTINCT cl2.link_group_id\n    FROM public.contact_links cl2\n    JOIN public.unified_contacts uc2 ON cl2.contact_id = uc2.id\n    WHERE uc2.tenant_org_id::uuid IN (\n      SELECT m.tenant_id\n      FROM public.user_tenant_memberships m\n      WHERE m.user_id = auth.uid() AND m.status = 'active'\n    )\n  );\n$function$\n","identity_arguments":""},{"name":"get_profile_role","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_profile_role(_user_id uuid)\n RETURNS text\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT p.role\n  FROM public.profiles p\n  WHERE p.id = _user_id\n    AND (\n      coalesce(auth.role(), '') = 'service_role'\n      OR auth.uid() = _user_id\n      OR public.is_system_admin(auth.uid())\n      OR public.shares_tenant_as_manager_pm(auth.uid(), _user_id)\n    );\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"get_profile_tenant_org_id","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_profile_tenant_org_id(_user_id uuid)\n RETURNS text\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT p.tenant_org_id\n  FROM public.profiles p\n  WHERE p.id = _user_id\n    AND (\n      coalesce(auth.role(), '') = 'service_role'\n      OR auth.uid() = _user_id\n      OR public.is_system_admin(auth.uid())\n      OR public.shares_tenant_as_manager_pm(auth.uid(), _user_id)\n    );\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"get_public_321_auto_unlock_brand","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_public_321_auto_unlock_brand()\n RETURNS TABLE(name text, logo_url text, company_phone text, company_email text, video_url text)\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  select\n    coalesce(nullif(btrim(t.name), ''), '321 Auto Unlock')::text as name,\n    coalesce(\n      nullif(btrim(t.company_logo_url), ''),\n      case\n        when nullif(btrim(t.settings ->> 'logo_ingest_b64'), '') is not null\n          then 'data:' || coalesce(nullif(btrim(t.settings ->> 'logo_ingest_mime'), ''), 'image/webp') || ';base64,' || (t.settings ->> 'logo_ingest_b64')\n        else null\n      end\n    )::text as logo_url,\n    nullif(btrim(t.company_phone), '')::text as company_phone,\n    nullif(btrim(t.company_email), '')::text as company_email,\n    case\n      when nullif(btrim(t.settings #>> '{media_branding,video_path}'), '') is null then null\n      else\n        'https://ymntrajfubicyxwwdxxa.supabase.co/storage/v1/object/public/' ||\n        coalesce(nullif(btrim(t.settings #>> '{media_branding,bucket}'), ''), 'generated-media') || '/' ||\n        (t.settings #>> '{media_branding,video_path}')\n    end::text as video_url\n  from public.tenants t\n  where t.id = 'd60e3c27-73ed-4a5f-a49b-c37636455daf'::uuid\n    and coalesce(t.status, 'active') = 'active'\n  limit 1;\n$function$\n","identity_arguments":""},{"name":"get_rep_call_velocity","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_rep_call_velocity(p_rep_id uuid, p_tenant_org_id text)\n RETURNS TABLE(calls_today integer, connects_today integer, last_contact_at timestamp with time zone)\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT\n    count(*) FILTER (WHERE event_type IN ('call_initiated','outbound_call') AND created_at >= date_trunc('day', now() AT TIME ZONE 'America/New_York'))::int,\n    count(*) FILTER (WHERE event_type IN ('call_completed','call_ended_by_rep','outbound_call') AND coalesce(duration_seconds,0) >= 20 AND created_at >= date_trunc('day', now() AT TIME ZONE 'America/New_York'))::int,\n    max(created_at) FILTER (WHERE event_type IN ('call_completed','call_ended_by_rep','outbound_call') AND coalesce(duration_seconds,0) >= 20)\n  FROM public.communication_events\n  WHERE public.is_tenant_member(p_tenant_org_id)\n    AND rep_id = p_rep_id\n    AND tenant_org_id = p_tenant_org_id;\n$function$\n","identity_arguments":"p_rep_id uuid, p_tenant_org_id text"},{"name":"get_revenue_pipeline_summary","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_revenue_pipeline_summary(p_tenant_id uuid)\n RETURNS TABLE(stage text, count bigint, amount numeric)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  -- Tenant access guard\n  IF NOT public.is_tenant_member(p_tenant_id) AND NOT public.is_system_admin() THEN\n    RAISE EXCEPTION 'Access denied to tenant %', p_tenant_id;\n  END IF;\n\n  RETURN QUERY\n  WITH contact_stage AS (\n    SELECT\n      c.id,\n      CASE\n        WHEN c.graduated_at IS NULL THEN 'new_leads'\n        WHEN LOWER(COALESCE(c.jobs_stage, c.claim_stage, '')) ~ 'complete|closed|paid' THEN 'completed'\n        WHEN LOWER(COALESCE(c.jobs_stage, c.claim_stage, '')) ~ 'sign|contract|approved' THEN 'signed'\n        ELSE 'in_progress'\n      END AS stage_key\n    FROM public.unified_contacts c\n    WHERE c.tenant_org_id = p_tenant_id\n      AND c.deleted_at IS NULL\n  ),\n  claim_amounts AS (\n    SELECT\n      cc.contact_id,\n      SUM(COALESCE(cc.settlement_amount, cc.fee_amount, 0)) AS total_amount\n    FROM public.contact_claims cc\n    WHERE cc.tenant_org_id = p_tenant_id\n    GROUP BY cc.contact_id\n  )\n  SELECT\n    cs.stage_key::text AS stage,\n    COUNT(*)::bigint AS count,\n    COALESCE(SUM(ca.total_amount), 0)::numeric AS amount\n  FROM contact_stage cs\n  LEFT JOIN claim_amounts ca ON ca.contact_id = cs.id\n  GROUP BY cs.stage_key;\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"get_rls_policies","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_rls_policies()\n RETURNS TABLE(schemaname text, tablename text, policyname text, permissive text, roles text[], cmd text, qual text, with_check text)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\nbegin\n  perform public.require_platform_operator();\n  return query\n    select p.schemaname::text, p.tablename::text, p.policyname::text,\n      p.permissive::text, p.roles::text[], p.cmd::text, p.qual::text,\n      p.with_check::text\n    from pg_catalog.pg_policies p\n    where p.schemaname = 'public'\n    order by p.tablename, p.policyname;\nend;\n$function$\n","identity_arguments":""},{"name":"get_table_columns","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_table_columns(p_table_name text)\n RETURNS TABLE(column_name text, data_type text, is_nullable text, column_default text)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\nbegin\n  perform public.require_platform_operator();\n  if not exists (\n    select 1\n    from pg_catalog.pg_class c\n    join pg_catalog.pg_namespace n on n.oid = c.relnamespace\n    where n.nspname = 'public'\n      and c.relname = p_table_name\n      and c.relkind in ('r', 'p', 'v', 'm')\n  ) then\n    raise exception 'unknown public relation' using errcode = '22023';\n  end if;\n\n  return query\n    select c.column_name::text, c.data_type::text, c.is_nullable::text,\n      c.column_default::text\n    from information_schema.columns c\n    where c.table_schema = 'public' and c.table_name = p_table_name\n    order by c.ordinal_position;\nend;\n$function$\n","identity_arguments":"p_table_name text"},{"name":"get_table_data","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_table_data(p_table_name text, p_limit_count integer DEFAULT 100)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\ndeclare\n  v_limit integer := greatest(1, least(coalesce(p_limit_count, 100), 500));\n  v_result jsonb;\nbegin\n  perform public.require_platform_operator();\n  if not exists (\n    select 1\n    from pg_catalog.pg_class c\n    join pg_catalog.pg_namespace n on n.oid = c.relnamespace\n    where n.nspname = 'public'\n      and c.relname = p_table_name\n      and c.relkind in ('r', 'p', 'v', 'm')\n  ) then\n    raise exception 'unknown public relation' using errcode = '22023';\n  end if;\n\n  execute format(\n    'select coalesce(jsonb_agg(to_jsonb(t)), ''[]''::jsonb)\n       from (select * from public.%I limit $1) t',\n    p_table_name\n  )\n  into v_result\n  using v_limit;\n\n  return coalesce(v_result, '[]'::jsonb);\nend;\n$function$\n","identity_arguments":"p_table_name text, p_limit_count integer"},{"name":"get_team_pipeline_summary","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_team_pipeline_summary(p_tenant_id uuid)\n RETURNS TABLE(user_id uuid, name text, email text, total_leads bigint, total_clients bigint, stale_count bigint, last_activity timestamp with time zone, stages jsonb)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  seven_days_ago timestamptz := now() - interval '7 days';\nBEGIN\n  IF NOT public.is_tenant_member(p_tenant_id) AND NOT public.is_system_admin() THEN\n    RAISE EXCEPTION 'Access denied to tenant %', p_tenant_id;\n  END IF;\n\n  RETURN QUERY\n  WITH assigned AS (\n    SELECT\n      c.assigned_to::uuid AS uid,\n      c.lead_stage,\n      c.jobs_stage,\n      c.graduated_at,\n      c.updated_at\n    FROM public.unified_contacts c\n    WHERE c.tenant_org_id = p_tenant_id\n      AND c.deleted_at IS NULL\n      AND c.assigned_to IS NOT NULL\n      AND c.assigned_to ~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'\n  ),\n  per_rep AS (\n    SELECT\n      a.uid,\n      COUNT(*) FILTER (WHERE a.graduated_at IS NULL)::bigint AS total_leads,\n      COUNT(*) FILTER (WHERE a.graduated_at IS NOT NULL)::bigint AS total_clients,\n      COUNT(*) FILTER (WHERE a.updated_at < seven_days_ago AND a.graduated_at IS NULL)::bigint AS stale_count,\n      MAX(a.updated_at) AS last_activity,\n      jsonb_object_agg(\n        COALESCE(\n          CASE WHEN a.graduated_at IS NOT NULL THEN a.jobs_stage ELSE a.lead_stage END,\n          'No Stage'\n        ),\n        cnt\n      ) AS stages\n    FROM (\n      SELECT\n        uid,\n        lead_stage,\n        jobs_stage,\n        graduated_at,\n        updated_at,\n        COUNT(*) OVER (PARTITION BY uid, COALESCE(\n          CASE WHEN graduated_at IS NOT NULL THEN jobs_stage ELSE lead_stage END,\n          'No Stage'\n        )) AS cnt\n      FROM assigned\n    ) a\n    GROUP BY a.uid\n  )\n  SELECT\n    pr.uid,\n    COALESCE(p.name, SPLIT_PART(p.email, '@', 1), 'Unknown')::text,\n    COALESCE(p.email, '')::text,\n    pr.total_leads,\n    pr.total_clients,\n    pr.stale_count,\n    pr.last_activity,\n    pr.stages\n  FROM per_rep pr\n  LEFT JOIN public.profiles p ON p.id = pr.uid\n  ORDER BY (pr.total_leads + pr.total_clients) DESC;\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"get_user_link_group_ids","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_user_link_group_ids()\n RETURNS SETOF uuid\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT DISTINCT cl.link_group_id\n  FROM public.contact_links cl\n  JOIN public.unified_contacts uc ON cl.contact_id = uc.id\n  WHERE uc.tenant_org_id::uuid IN (\n    SELECT m.tenant_id\n    FROM public.user_tenant_memberships m\n    WHERE m.user_id = auth.uid() AND m.status = 'active'\n  );\n$function$\n","identity_arguments":""},{"name":"get_user_pending_agreements","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_user_pending_agreements(p_user_id uuid, p_tenant_id uuid)\n RETURNS TABLE(template_id uuid, template_type text, template_name text, template_version integer, effective_date date, display_order integer, short_description text, reason text)\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_caller uuid := auth.uid();\n  v_tenant_type text;\n  v_role text;\nBEGIN\n  IF v_caller IS NULL THEN RAISE EXCEPTION 'not_authenticated' USING ERRCODE='42501'; END IF;\n  IF v_caller <> p_user_id\n     AND NOT public.is_system_admin(v_caller)\n     AND NOT public.is_manager_or_higher(v_caller, p_tenant_id) THEN\n    RAISE EXCEPTION 'agreement_access_denied' USING ERRCODE='42501';\n  END IF;\n  IF NOT public.is_tenant_member(v_caller, p_tenant_id) AND NOT public.is_system_admin(v_caller) THEN\n    RAISE EXCEPTION 'tenant_access_denied' USING ERRCODE='42501';\n  END IF;\n\n  SELECT t.tenant_type INTO v_tenant_type FROM public.tenant_organizations t WHERE t.id=p_tenant_id;\n  SELECT ur.role::text INTO v_role\n  FROM public.user_roles ur\n  WHERE ur.user_id=p_user_id AND (ur.tenant_id=p_tenant_id OR ur.tenant_id IS NULL)\n  ORDER BY CASE ur.role::text WHEN 'GodMode' THEN 1 WHEN 'Admin' THEN 2 WHEN 'Owner' THEN 3 WHEN 'Tenant Owner' THEN 3 WHEN 'Manager' THEN 4 WHEN 'Rep' THEN 5 ELSE 9 END\n  LIMIT 1;\n\n  RETURN QUERY\n  WITH applicable_requirements AS (\n    SELECT DISTINCT ON (req.template_type) req.template_type, req.min_version, req.display_order\n    FROM public.agreement_requirements req\n    WHERE req.is_required=true\n      AND (req.tenant_id IS NULL OR req.tenant_id=p_tenant_id)\n      AND (req.tenant_type IS NULL OR req.tenant_type=v_tenant_type)\n      AND (req.role IS NULL OR req.role=v_role)\n    ORDER BY req.template_type, (req.tenant_id IS NOT NULL) DESC, req.min_version DESC\n  ), active_templates AS (\n    SELECT DISTINCT ON (t.template_type) t.id,t.template_type,t.template_name,t.version,t.effective_date,t.short_description,t.requires_reacceptance_on_bump\n    FROM public.agreement_templates t WHERE t.is_active=true ORDER BY t.template_type,t.version DESC\n  ), user_latest_signed AS (\n    SELECT DISTINCT ON (sa.agreement_type) sa.agreement_type AS template_type,sa.template_version_at_signing,sa.signed_at,sa.status\n    FROM public.signed_agreements sa\n    WHERE sa.user_id=p_user_id AND (sa.tenant_id=p_tenant_id OR sa.tenant_id IS NULL) AND sa.status='signed'\n    ORDER BY sa.agreement_type,sa.signed_at DESC\n  )\n  SELECT at.id,at.template_type,at.template_name,at.version,at.effective_date,coalesce(ar.display_order,100),at.short_description,\n    CASE WHEN uls.template_type IS NULL OR uls.template_version_at_signing IS NULL THEN 'never_signed'\n         WHEN uls.template_version_at_signing < at.version AND at.requires_reacceptance_on_bump THEN 'reacceptance_required'\n         WHEN uls.template_version_at_signing < ar.min_version THEN 'version_outdated'\n         ELSE NULL END\n  FROM applicable_requirements ar\n  JOIN active_templates at ON at.template_type=ar.template_type\n  LEFT JOIN user_latest_signed uls ON uls.template_type=ar.template_type\n  WHERE uls.template_type IS NULL OR uls.template_version_at_signing IS NULL OR uls.template_version_at_signing < ar.min_version OR (uls.template_version_at_signing < at.version AND at.requires_reacceptance_on_bump)\n  ORDER BY coalesce(ar.display_order,100),at.template_type;\nEND;\n$function$\n","identity_arguments":"p_user_id uuid, p_tenant_id uuid"},{"name":"get_user_tenant_org_id","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_user_tenant_org_id()\n RETURNS text\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT tenant_org_id FROM profiles WHERE id = auth.uid() LIMIT 1;\n$function$\n","identity_arguments":""},{"name":"get_zoho_mail_platform_credentials","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.get_zoho_mail_platform_credentials()\n RETURNS TABLE(client_id text, client_secret text)\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\n  select\n    max(case when name = 'knocklaunch_zoho_mail_client_id' then decrypted_secret end)::text as client_id,\n    max(case when name = 'knocklaunch_zoho_mail_client_secret' then decrypted_secret end)::text as client_secret\n  from vault.decrypted_secrets\n  where name in ('knocklaunch_zoho_mail_client_id', 'knocklaunch_zoho_mail_client_secret');\n$function$\n","identity_arguments":""},{"name":"guard_communication_setup_request_update","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.guard_communication_setup_request_update()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nbegin\n  if public.is_system_admin() then\n    new.updated_at := now();\n    if new.status in ('connected', 'declined') and old.status is distinct from new.status then\n      new.resolved_at := coalesce(new.resolved_at, now());\n      new.resolved_by := coalesce(new.resolved_by, auth.uid());\n    end if;\n    return new;\n  end if;\n\n  if not public.is_tenant_member(auth.uid(), old.tenant_id) then\n    raise exception 'tenant access denied';\n  end if;\n  if old.status not in ('requested', 'needs_info') then\n    raise exception 'request is already being handled by KnockLaunch';\n  end if;\n  if new.tenant_id is distinct from old.tenant_id\n     or new.channel is distinct from old.channel\n     or new.status is distinct from old.status\n     or new.admin_notes is distinct from old.admin_notes\n     or new.resolved_by is distinct from old.resolved_by\n     or new.resolved_at is distinct from old.resolved_at\n     or new.requested_by is distinct from old.requested_by then\n    raise exception 'only request details can be changed by the tenant';\n  end if;\n\n  new.updated_at := now();\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"handle_call_designation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.handle_call_designation(p_tenant_id uuid, p_lead_id text, p_user_id uuid DEFAULT NULL::uuid, p_designation text DEFAULT 'NEW'::text, p_notes text DEFAULT NULL::text, p_appt_date text DEFAULT NULL::text, p_appt_time text DEFAULT NULL::text, p_assignee text DEFAULT NULL::text, p_phone_called text DEFAULT NULL::text, p_duration_seconds integer DEFAULT NULL::integer, p_metadata jsonb DEFAULT NULL::jsonb)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user_id UUID;\n  v_caller_email TEXT;\n  v_status TEXT;\n  v_lead_stage TEXT;  -- NEW: Pre-pipeline stage mapping\n  v_call_outcome call_outcome;\n  v_followup_date DATE;\n  v_call_log_id UUID;\n  v_lead_name TEXT;\n  v_lead_address TEXT;\n  v_lead_city TEXT;\n  v_lead_state TEXT;\n  v_lead_zip TEXT;\n  v_lead_phone TEXT;\n  v_lead_email TEXT;\n  v_contact_id UUID;\n  v_should_delete BOOLEAN := false;\n  v_should_graduate BOOLEAN := false;  -- NEW: Graduation trigger\n  v_move_to_roof_queue BOOLEAN := false;\n  v_roof_queue_reason TEXT;\n  v_result JSONB;\nBEGIN\n  v_user_id := auth.uid();\n\n  IF v_user_id IS NULL THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Authentication required');\n  END IF;\n\n  IF NOT public.is_tenant_member(v_user_id, p_tenant_id) THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Tenant access denied');\n  END IF;\n\n  IF p_user_id IS NOT NULL AND p_user_id IS DISTINCT FROM v_user_id THEN\n    IF NOT public.is_manager_or_higher(v_user_id, p_tenant_id) OR NOT public.is_tenant_member(p_user_id, p_tenant_id) THEN\n      RETURN jsonb_build_object('ok', false, 'error', 'User scope denied');\n    END IF;\n    v_user_id := p_user_id;\n  END IF;\n\n  -- Get caller email\n  SELECT email INTO v_caller_email FROM auth.users WHERE id = v_user_id LIMIT 1;\n  IF v_caller_email IS NULL THEN\n    SELECT email INTO v_caller_email FROM profiles WHERE id = v_user_id LIMIT 1;\n  END IF;\n\n  -- Get lead details\n  SELECT name, address, city, state, zip, phone, email \n  INTO v_lead_name, v_lead_address, v_lead_city, v_lead_state, v_lead_zip, v_lead_phone, v_lead_email\n  FROM lead_deck WHERE lead_id = p_lead_id AND tenant_org_id = p_tenant_id::text LIMIT 1;\n\n  -- Map designation to BOTH status AND lead_stage (pre-pipeline stage)\n  CASE p_designation\n    WHEN 'NEW' THEN \n      v_status := 'New'; \n      v_lead_stage := 'New / Unassigned';\n      v_call_outcome := 'interested';\n    WHEN 'APPT_SET' THEN \n      v_status := 'Appointment'; \n      v_lead_stage := 'Appointment Set';\n      v_call_outcome := 'appointment_set';\n      v_should_graduate := true;  -- Graduation trigger!\n    WHEN 'APPT_RESCHEDULE' THEN \n      v_status := 'Appointment'; \n      v_lead_stage := 'Appointment Set';\n      v_call_outcome := 'appointment_set';\n      v_should_graduate := true;\n    WHEN 'APPT_CONFIRMED' THEN \n      v_status := 'Appointment'; \n      v_lead_stage := 'Appointment Set';\n      v_call_outcome := 'appointment_set';\n      v_should_graduate := true;\n    WHEN 'QUALIFIED' THEN \n      v_status := 'Qualified'; \n      v_lead_stage := 'Qualified';\n      v_call_outcome := 'qualified';\n    WHEN 'NOT_QUALIFIED' THEN \n      v_status := 'Not Qualified'; \n      v_lead_stage := 'Not Interested';\n      v_call_outcome := 'not_qualified';\n    WHEN 'CALLBACK', 'CALLBACK_REQ' THEN \n      v_status := 'Needs Follow Up'; \n      v_lead_stage := 'Callback Requested';\n      v_call_outcome := 'callback_requested';\n      v_followup_date := COALESCE(p_appt_date::date, CURRENT_DATE + INTERVAL '7 days');\n    WHEN 'BUSY_RETRY' THEN \n      v_status := 'Needs Follow Up'; \n      v_lead_stage := 'Callback Requested';\n      v_call_outcome := 'callback_requested';\n      v_followup_date := CURRENT_DATE + INTERVAL '1 day';\n    WHEN 'NO_ANSWER' THEN \n      v_status := 'No Answer'; \n      v_lead_stage := 'No Answer';\n      v_call_outcome := 'no_answer';\n    WHEN 'LEFT_VM', 'VOICEMAIL' THEN \n      v_status := 'Voicemail'; \n      v_lead_stage := 'Left Voicemail';\n      v_call_outcome := 'voicemail';\n    WHEN 'TEXT_SENT' THEN \n      v_status := 'Contacted'; \n      v_lead_stage := 'Text Sent';\n      v_call_outcome := 'qualified';\n    WHEN 'EMAIL_SENT' THEN \n      v_status := 'Contacted'; \n      v_lead_stage := 'Email Sent';\n      v_call_outcome := 'qualified';\n    WHEN 'WRONG_NUMBER' THEN \n      v_status := 'Wrong Number'; \n      v_lead_stage := 'Bad Lead';\n      v_call_outcome := 'wrong_number';\n    WHEN 'DISCONNECTED' THEN \n      v_status := 'Disconnected'; \n      v_lead_stage := 'Bad Lead';\n      v_call_outcome := 'wrong_number';\n    WHEN 'DNC', 'DO_NOT_CALL' THEN \n      v_status := 'DNC'; \n      v_lead_stage := 'Do Not Call';\n      v_call_outcome := 'dnc_requested';\n    WHEN 'NOT_INTERESTED' THEN \n      v_status := 'Not Interested'; \n      v_lead_stage := 'Not Interested';\n      v_call_outcome := 'not_interested';\n    WHEN 'BAD_LEAD' THEN \n      v_status := 'Not Qualified'; \n      v_lead_stage := 'Bad Lead';\n      v_call_outcome := 'not_qualified';\n    WHEN 'NEW_ROOF' THEN \n      v_status := 'New Roof Queue'; \n      v_lead_stage := 'New Roof Queue';\n      v_call_outcome := 'not_qualified';\n      v_move_to_roof_queue := true;\n      v_roof_queue_reason := 'NEW_ROOF';\n    WHEN 'METAL_ROOF' THEN \n      v_status := 'Not Qualified - Metal'; \n      v_lead_stage := 'Metal Roof';\n      v_call_outcome := 'not_qualified';\n      v_move_to_roof_queue := true;\n      v_roof_queue_reason := 'METAL_ROOF';\n    WHEN 'INSPECTION_DONE' THEN \n      v_status := 'Inspection Complete'; \n      v_lead_stage := 'Appointment Set';  -- Keep at graduated stage\n      v_call_outcome := 'qualified';\n      v_should_graduate := true;\n    WHEN 'TARPED' THEN \n      v_status := 'Tarped'; \n      v_lead_stage := 'Appointment Set';\n      v_call_outcome := 'qualified';\n      v_should_graduate := true;\n    WHEN 'PA_REFERRAL_OFFERED' THEN \n      v_status := 'PA Referral Offered'; \n      v_lead_stage := 'Qualified';\n      v_call_outcome := 'qualified';\n    WHEN 'PA_REFERRAL_ACCEPTED' THEN \n      v_status := 'PA Referral'; \n      v_lead_stage := 'PA Referral';\n      v_call_outcome := 'qualified';\n    WHEN 'ESCALATE_PA' THEN \n      v_status := 'Escalated to PA'; \n      v_lead_stage := 'PA Referral';\n      v_call_outcome := 'qualified';\n    WHEN 'ESCALATE_ROOFER' THEN \n      v_status := 'Escalated to Roofer'; \n      v_lead_stage := 'Qualified';\n      v_call_outcome := 'qualified';\n    WHEN 'SKIP' THEN \n      v_status := 'Skipped'; \n      v_lead_stage := NULL;  -- Don't change lead_stage on skip\n      v_call_outcome := 'no_answer';\n    ELSE \n      v_status := 'New'; \n      v_lead_stage := 'New / Unassigned';\n      v_call_outcome := 'interested';\n  END CASE;\n\n  -- Log the call\n  INSERT INTO call_logs (user_id, tenant_id, lead_id, phone_called, outcome, notes, callback_date, duration_seconds, lead_name, lead_address, city, state, zip, metadata)\n  VALUES (v_user_id, p_tenant_id, p_lead_id, COALESCE(p_phone_called, ''), v_call_outcome, p_notes, p_appt_date, p_duration_seconds, v_lead_name, v_lead_address, v_lead_city, v_lead_state, v_lead_zip, p_metadata)\n  RETURNING id INTO v_call_log_id;\n\n  -- Handle roof queue routing\n  IF v_move_to_roof_queue THEN\n    INSERT INTO new_roofs_queue (\n      lead_id, tenant_org_id, name, phone, email, address, city, state, zip,\n      moved_by, moved_to_queue_at, reason, status, notes\n    ) VALUES (\n      p_lead_id, p_tenant_id::text, v_lead_name, v_lead_phone, v_lead_email, \n      v_lead_address, v_lead_city, v_lead_state, v_lead_zip,\n      v_caller_email, NOW(), v_roof_queue_reason, 'queued', p_notes\n    ) ON CONFLICT (lead_id, tenant_org_id) DO UPDATE SET\n      moved_by = v_caller_email,\n      moved_to_queue_at = NOW(),\n      reason = v_roof_queue_reason,\n      status = 'queued',\n      notes = COALESCE(new_roofs_queue.notes || E'\\n\\n', '') || '[' || now()::date || '] ' || COALESCE(p_notes, 'Moved to roof queue'),\n      updated_at = NOW();\n    \n    -- Soft delete from main tables\n    UPDATE unified_contacts SET \n      deleted_at = NOW(),\n      deleted_by = v_caller_email,\n      deletion_reason = v_roof_queue_reason || ': ' || COALESCE(p_notes, 'Moved to roof queue'),\n      status = v_status,\n      lead_stage = v_lead_stage,\n      updated_at = NOW()\n    WHERE lead_id = p_lead_id AND tenant_org_id = p_tenant_id::text AND deleted_at IS NULL;\n    \n    UPDATE lead_deck SET \n      deleted_at = NOW(),\n      deleted_by = v_caller_email,\n      deletion_reason = v_roof_queue_reason || ': ' || COALESCE(p_notes, 'Moved to roof queue'),\n      status = v_status,\n      lead_stage = v_lead_stage,\n      updated_at = NOW()\n    WHERE lead_id = p_lead_id AND tenant_org_id = p_tenant_id::text AND deleted_at IS NULL;\n    \n    RETURN jsonb_build_object(\n      'ok', true, \n      'designation', p_designation, \n      'status', v_status, \n      'lead_stage', v_lead_stage,\n      'call_log_id', v_call_log_id, \n      'lead_id', p_lead_id, \n      'assigned_to', v_caller_email, \n      'deleted', true,\n      'moved_to_roof_queue', true,\n      'roof_queue_reason', v_roof_queue_reason,\n      'timestamp', NOW()\n    );\n  END IF;\n\n  -- Check for delete cases\n  v_should_delete := p_designation IN ('DNC', 'DO_NOT_CALL', 'NOT_QUALIFIED', 'BAD_LEAD');\n\n  IF v_should_delete THEN\n    DELETE FROM unified_contacts WHERE lead_id = p_lead_id AND tenant_org_id = p_tenant_id::text;\n    DELETE FROM lead_deck WHERE lead_id = p_lead_id AND tenant_org_id = p_tenant_id::text;\n  ELSE\n    -- Upsert to unified_contacts with BOTH status AND lead_stage\n    INSERT INTO unified_contacts (\n      lead_id, tenant_org_id, name, first_name, last_name, phone, email, address, \n      city, state, zip, contact_status, status, lead_stage, \n      assigned_to, assigned_rep, appt_date, appt_time, notes, \n      graduated_at, jobs_stage, claim_stage,\n      created_at, updated_at\n    )\n    SELECT \n      p_lead_id, p_tenant_id::text, COALESCE(v_lead_name, ''), \n      split_part(COALESCE(v_lead_name, ''), ' ', 1),\n      CASE WHEN position(' ' in COALESCE(v_lead_name, '')) > 0 \n           THEN substring(COALESCE(v_lead_name, '') from position(' ' in COALESCE(v_lead_name, '')) + 1) \n           ELSE '' END,\n      COALESCE(v_lead_phone, ''), COALESCE(v_lead_email, ''), COALESCE(v_lead_address, ''),\n      v_lead_city, v_lead_state, v_lead_zip,\n      v_status, v_status, v_lead_stage,\n      COALESCE(p_assignee, v_caller_email), COALESCE(p_assignee, v_caller_email), \n      p_appt_date, p_appt_time, p_notes,\n      CASE WHEN v_should_graduate THEN NOW() ELSE NULL END,\n      CASE WHEN v_should_graduate THEN 'Appointment Scheduled' ELSE NULL END,\n      CASE WHEN v_should_graduate THEN 'Inspection Scheduled' ELSE NULL END,\n      NOW(), NOW()\n    ON CONFLICT (lead_id, tenant_org_id) DO UPDATE SET\n      contact_status = v_status, \n      status = v_status,\n      lead_stage = COALESCE(v_lead_stage, unified_contacts.lead_stage),  -- Update lead_stage!\n      assigned_to = COALESCE(p_assignee, v_caller_email, unified_contacts.assigned_to),\n      assigned_rep = COALESCE(p_assignee, v_caller_email, unified_contacts.assigned_rep),\n      appt_date = CASE WHEN p_appt_date IS NOT NULL THEN p_appt_date ELSE unified_contacts.appt_date END,\n      appt_time = CASE WHEN p_appt_time IS NOT NULL THEN p_appt_time ELSE unified_contacts.appt_time END,\n      notes = CASE WHEN p_notes IS NOT NULL \n              THEN COALESCE(unified_contacts.notes || E'\\n\\n', '') || '[' || now()::date || '] ' || p_notes \n              ELSE unified_contacts.notes END,\n      -- Handle graduation\n      graduated_at = CASE WHEN v_should_graduate AND unified_contacts.graduated_at IS NULL THEN NOW() ELSE unified_contacts.graduated_at END,\n      jobs_stage = CASE WHEN v_should_graduate AND unified_contacts.jobs_stage IS NULL THEN 'Appointment Scheduled' ELSE unified_contacts.jobs_stage END,\n      claim_stage = CASE WHEN v_should_graduate AND unified_contacts.claim_stage IS NULL THEN 'Inspection Scheduled' ELSE unified_contacts.claim_stage END,\n      updated_at = NOW()\n    RETURNING id INTO v_contact_id;\n\n    -- Also update lead_deck with lead_stage\n    UPDATE lead_deck SET \n      status = v_status, \n      lead_stage = COALESCE(v_lead_stage, lead_stage),  -- Update lead_stage!\n      assigned_to = COALESCE(p_assignee, v_caller_email, assigned_to),\n      notes = CASE WHEN p_notes IS NOT NULL \n              THEN COALESCE(notes || E'\\n\\n', '') || '[' || now()::date || '] ' || p_notes \n              ELSE notes END, \n      -- Handle graduation\n      graduated_at = CASE WHEN v_should_graduate AND graduated_at IS NULL THEN NOW() ELSE graduated_at END,\n      updated_at = NOW()\n    WHERE lead_id = p_lead_id AND tenant_org_id = p_tenant_id::text;\n  END IF;\n\n  -- Create follow-up if callback requested\n  IF p_designation IN ('CALLBACK', 'CALLBACK_REQ', 'BUSY_RETRY') OR v_status = 'Needs Follow Up' THEN\n    INSERT INTO followups (lead_id, rep_email, customer_name, followup_date, notes, status, tenant_org_id)\n    SELECT p_lead_id, p.email, v_lead_name, v_followup_date, COALESCE(p_notes, 'Follow up needed'), 'Pending', p_tenant_id::text\n    FROM profiles p WHERE p.id = v_user_id \n    ON CONFLICT DO NOTHING;\n  END IF;\n\n  -- Add to DNC list if requested\n  IF p_designation IN ('DNC', 'DO_NOT_CALL') AND p_phone_called IS NOT NULL THEN\n    INSERT INTO dnc_list (phone, name, reason, added_by, tenant_org_id)\n    SELECT p_phone_called, v_lead_name, COALESCE(p_notes, 'DNC requested during call'), p.email, p_tenant_id::text\n    FROM profiles p WHERE p.id = v_user_id \n    ON CONFLICT (phone) DO NOTHING;\n  END IF;\n\n  RETURN jsonb_build_object(\n    'ok', true, \n    'designation', p_designation, \n    'status', v_status, \n    'lead_stage', v_lead_stage,\n    'graduated', v_should_graduate,\n    'call_log_id', v_call_log_id, \n    'contact_id', v_contact_id,\n    'lead_id', p_lead_id, \n    'assigned_to', COALESCE(p_assignee, v_caller_email), \n    'deleted', v_should_delete, \n    'timestamp', NOW()\n  );\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_lead_id text, p_user_id uuid, p_designation text, p_notes text, p_appt_date text, p_appt_time text, p_assignee text, p_phone_called text, p_duration_seconds integer, p_metadata jsonb"},{"name":"handle_new_user","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.handle_new_user()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nbegin\n  insert into public.profiles (id, email, phone, name)\n  values (\n    new.id,\n    nullif(btrim(new.email), ''),\n    nullif(btrim(new.phone), ''),\n    coalesce(\n      nullif(new.raw_user_meta_data->>'full_name', ''),\n      nullif(new.raw_user_meta_data->>'name', ''),\n      nullif(btrim(new.email), ''),\n      nullif(btrim(new.phone), ''),\n      'KnockLaunch User'\n    )\n  )\n  on conflict (id) do update\n  set email = excluded.email,\n      phone = coalesce(excluded.phone, public.profiles.phone),\n      name = coalesce(nullif(public.profiles.name, ''), excluded.name),\n      updated_at = now();\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"has_acting_pm_grant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.has_acting_pm_grant(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role'\n     AND auth.uid() IS DISTINCT FROM _user_id\n     AND NOT coalesce(public.is_system_admin(auth.uid()),false)\n     AND NOT coalesce(public.is_manager_or_higher(auth.uid(),_tenant_id),false) THEN\n    RAISE EXCEPTION 'acting PM grant introspection denied' USING ERRCODE='42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.acting_pm_grants\n    WHERE user_id=_user_id AND tenant_id=_tenant_id\n      AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at > now())\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"has_any_active_tenant_membership","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.has_any_active_tenant_membership(_user_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role'\n     AND auth.uid() IS DISTINCT FROM _user_id\n     AND NOT coalesce(public.is_system_admin(auth.uid()),false) THEN\n    RAISE EXCEPTION 'membership introspection denied' USING ERRCODE='42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships\n    WHERE user_id=_user_id AND status='active'\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"has_entitlement","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.has_entitlement(_tenant_id uuid, _feature_key text)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(auth.uid(), _tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant entitlement access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN public.is_tenant_comped(_tenant_id) OR EXISTS (\n    SELECT 1 FROM public.tenant_subscriptions ts\n    JOIN public.plan_features pf ON pf.plan_id = ts.plan_id\n    WHERE ts.tenant_id = _tenant_id AND pf.feature_key = _feature_key\n      AND ts.status IN ('trial','active','past_due')\n      AND ((pf.is_boolean = true AND coalesce(pf.limit_value,0) > 0)\n        OR (pf.is_boolean = false AND (pf.limit_value IS NULL OR pf.limit_value <> 0)))\n  );\nEND;\n$function$\n","identity_arguments":"_tenant_id uuid, _feature_key text"},{"name":"has_role","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.has_role(_user_id uuid, _tenant_id uuid, _role app_role)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role'\n     AND auth.uid() IS DISTINCT FROM _user_id\n     AND NOT coalesce(public.is_system_admin(auth.uid()),false)\n     AND NOT coalesce(public.is_manager_or_higher(auth.uid(),_tenant_id),false) THEN\n    RAISE EXCEPTION 'role introspection denied' USING ERRCODE='42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1\n    FROM public.user_tenant_memberships m\n    JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active' AND ur.role=_role\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid, _role app_role"},{"name":"has_user_accepted_required_agreements","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.has_user_accepted_required_agreements(p_user_id uuid, p_tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE v_pending_count integer;\nBEGIN\n  IF p_user_id IS NULL OR p_tenant_id IS NULL THEN RETURN false; END IF;\n  SELECT count(*) INTO v_pending_count FROM public.get_user_pending_agreements(p_user_id, p_tenant_id);\n  RETURN v_pending_count = 0;\nEND;\n$function$\n","identity_arguments":"p_user_id uuid, p_tenant_id uuid"},{"name":"increment_active_enrollments","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.increment_active_enrollments(p_sequence_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  UPDATE communication_sequences\n  SET active_enrollments = COALESCE(active_enrollments, 0) + 1,\n      total_enrollments = COALESCE(total_enrollments, 0) + 1\n  WHERE id = p_sequence_id;\nEND;\n$function$\n","identity_arguments":"p_sequence_id uuid"},{"name":"is_admin_or_higher","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_admin_or_higher(_user_id uuid, _tenant_id uuid DEFAULT NULL::uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(_user_id) OR (_tenant_id IS NOT NULL AND EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Admin','TenantOwner','Tenant Owner','Owner','GodMode'))));\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_assigned_to","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_assigned_to(_user_id uuid, _assigned_to text)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nDECLARE v_email text;\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role'\n     AND auth.uid() IS DISTINCT FROM _user_id\n     AND NOT coalesce(public.is_system_admin(auth.uid()),false) THEN\n    RAISE EXCEPTION 'assignment introspection denied' USING ERRCODE='42501';\n  END IF;\n  SELECT email INTO v_email FROM public.profiles WHERE id=_user_id;\n  RETURN _assigned_to=_user_id::text OR lower(_assigned_to)=lower(v_email);\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _assigned_to text"},{"name":"is_claim_participant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_claim_participant(_claim_id uuid, _user_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1\n    FROM shared_claim_participants scp\n    JOIN user_tenant_memberships utm ON utm.tenant_id = scp.tenant_id\n    WHERE scp.shared_claim_id = _claim_id\n      AND utm.user_id = _user_id\n      AND utm.status = 'active'\n      AND scp.status = 'accepted'\n  ) OR EXISTS (\n    SELECT 1\n    FROM shared_claims sc\n    JOIN user_tenant_memberships utm ON utm.tenant_id = sc.created_by_tenant_id\n    WHERE sc.id = _claim_id\n      AND utm.user_id = _user_id\n      AND utm.status = 'active'\n  ) OR public.is_system_admin(_user_id)\n$function$\n","identity_arguments":"_claim_id uuid, _user_id uuid"},{"name":"is_claim_participant_any_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_claim_participant_any_status(_claim_id uuid, _user_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1\n    FROM shared_claim_participants scp\n    JOIN user_tenant_memberships utm ON utm.tenant_id = scp.tenant_id\n    WHERE scp.shared_claim_id = _claim_id\n      AND utm.user_id = _user_id\n      AND utm.status = 'active'\n  ) OR public.is_system_admin(_user_id)\n$function$\n","identity_arguments":"_claim_id uuid, _user_id uuid"},{"name":"is_command_agent","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_command_agent(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(_user_id)\n    OR EXISTS (\n      SELECT 1\n      FROM public.user_tenant_memberships m\n      JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n      WHERE m.user_id=_user_id\n        AND m.tenant_id=_tenant_id\n        AND m.status='active'\n        AND ur.role::text IN ('GodMode','Admin','Owner','Tenant Owner','Manager','command_agent')\n    );\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_door_accessible","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_door_accessible(p_door_tenant_id text, p_created_by uuid, p_last_visited_by uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(auth.uid()) OR auth.uid()=p_created_by OR auth.uid()=p_last_visited_by OR EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=auth.uid() AND m.tenant_id::text=p_door_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Owner','Tenant Owner','Admin','GodMode')));\n$function$\n","identity_arguments":"p_door_tenant_id text, p_created_by uuid, p_last_visited_by uuid"},{"name":"is_existing_client_record","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_existing_client_record(p_status text, p_lead_stage text, p_jobs_stage text, p_claim_stage text, p_graduated_at timestamp with time zone)\n RETURNS boolean\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT\n    p_graduated_at IS NOT NULL\n    OR LOWER(COALESCE(p_status,'')) ~ '(client|customer|active|job|approved|signed|contract|in progress|in-progress|inprogress)'\n    OR LOWER(COALESCE(p_jobs_stage,'')) ~ '(active|approved|signed|contract|in progress|complete|paid)'\n    OR LOWER(COALESCE(p_claim_stage,'')) ~ '(active|approved|signed|contract|in progress|complete|paid|settled)';\n$function$\n","identity_arguments":"p_status text, p_lead_stage text, p_jobs_stage text, p_claim_stage text, p_graduated_at timestamp with time zone"},{"name":"is_global_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_global_admin(_user_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$ SELECT public.is_system_admin(_user_id); $function$\n","identity_arguments":"_user_id uuid"},{"name":"is_manager_or_higher","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_manager_or_higher(_user_id uuid, _tenant_id uuid DEFAULT NULL::uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(_user_id) OR (_tenant_id IS NOT NULL AND EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Manager','PM','OfficeAdmin','Office Staff','Admin','TenantOwner','Tenant Owner','Owner','GodMode'))));\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_manager_or_higher_strict","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_manager_or_higher_strict(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role'\n     AND auth.uid() IS DISTINCT FROM _user_id\n     AND NOT coalesce(public.is_system_admin(auth.uid()),false)\n     AND NOT coalesce(public.is_manager_or_higher(auth.uid(),_tenant_id),false) THEN\n    RAISE EXCEPTION 'manager-role introspection denied' USING ERRCODE='42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1\n    FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Manager','PM','Admin','Owner','Tenant Owner','GodMode'))\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_manager_pm_or_higher","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_manager_pm_or_higher(_user uuid, _tenant uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(_user) OR EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user AND m.tenant_id=_tenant AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Manager','PM','Admin','Owner','Tenant Owner','SandboxOwner','GodMode')));\n$function$\n","identity_arguments":"_user uuid, _tenant uuid"},{"name":"is_platform_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_platform_admin(_user_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$ SELECT public.is_system_admin(_user_id); $function$\n","identity_arguments":"_user_id uuid"},{"name":"is_realtor_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_realtor_tenant(_tenant_org_id text)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(_tenant_org_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant type access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.tenants t\n    WHERE t.id::text = _tenant_org_id AND upper(t.tenant_type) = 'REALTOR'\n  );\nEND;\n$function$\n","identity_arguments":"_tenant_org_id text"},{"name":"is_repo_agent_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_repo_agent_admin()\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1 FROM auth.users\n    WHERE id = auth.uid()\n      AND lower(coalesce(email, '')) = 'info@knocklaunch.app'\n  );\n$function$\n","identity_arguments":""},{"name":"is_system_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_system_admin()\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$ SELECT public.is_system_admin(auth.uid()); $function$\n","identity_arguments":""},{"name":"is_system_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_system_admin(_user_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1\n    FROM public.user_roles\n    WHERE user_id = _user_id\n      AND role::text IN ('GodMode','PlatformAdmin','Admin')\n      AND tenant_id IS NULL\n  )\n  OR EXISTS (\n    SELECT 1\n    FROM auth.users au\n    WHERE au.id = _user_id\n      AND lower(coalesce(au.email, '')) IN (\n        'info@knocklaunch.app',\n        'noelmal2289@gmail.com'\n      )\n  );\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"is_tenant_comped","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_comped(_tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(auth.uid(), _tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant billing access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.billing_comps c\n    WHERE c.is_active = true AND c.scope = 'tenant' AND c.tenant_id = _tenant_id\n      AND (c.expires_at IS NULL OR c.expires_at > now())\n  );\nEND;\n$function$\n","identity_arguments":"_tenant_id uuid"},{"name":"is_tenant_crew_only","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_crew_only(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role'\n     AND auth.uid() IS DISTINCT FROM _user_id\n     AND NOT coalesce(public.is_system_admin(auth.uid()),false)\n     AND NOT coalesce(public.is_manager_or_higher(auth.uid(),_tenant_id),false) THEN\n    RAISE EXCEPTION 'crew-role introspection denied' USING ERRCODE='42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships m\n    JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active' AND ur.role::text='Crew'\n  ) AND NOT EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships m2\n    JOIN public.user_roles ur2 ON ur2.user_id=m2.user_id AND ur2.tenant_id=m2.tenant_id\n    WHERE m2.user_id=_user_id AND m2.tenant_id=_tenant_id AND m2.status='active' AND ur2.role::text<>'Crew'\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_tenant_member","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_member(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(_user_id) OR EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active');\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_tenant_member","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_member(check_tenant_id text)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT check_tenant_id IS NOT NULL AND (public.is_system_admin(auth.uid()) OR EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships m\n    WHERE m.user_id=auth.uid() AND m.tenant_id::text=check_tenant_id AND m.status='active'));\n$function$\n","identity_arguments":"check_tenant_id text"},{"name":"is_tenant_owner","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_owner(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('TenantOwner','Tenant Owner','Owner')));\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_tenant_owner_for","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_owner_for(_user_id uuid, _tenant_id text)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1\n    FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id\n      AND m.tenant_id::text=_tenant_id\n      AND m.status='active'\n      AND (m.is_owner=true OR ur.role IN ('Owner','Tenant Owner'))\n  );\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id text"},{"name":"is_tenant_owner_membership","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_owner_membership(_viewer uuid, _tenant uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships utm\n    WHERE utm.user_id = _viewer\n      AND utm.tenant_id = _tenant\n      AND utm.is_owner = true\n      AND utm.status = 'active'\n  )\n$function$\n","identity_arguments":"_viewer uuid, _tenant uuid"},{"name":"is_tenant_owner_or_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_tenant_owner_or_admin(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(_user_id) OR EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=_user_id AND m.tenant_id=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Owner','Tenant Owner','Admin','GodMode')));\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_trial_tenant_active","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_trial_tenant_active(_tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(auth.uid(), _tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant trial access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.trial_accounts\n    WHERE tenant_id = _tenant_id AND trial_status = 'active'\n      AND (trial_end_date IS NULL OR trial_end_date > now())\n  );\nEND;\n$function$\n","identity_arguments":"_tenant_id uuid"},{"name":"is_user_active","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_user_active(_user_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         auth.uid() IS DISTINCT FROM _user_id\n         AND NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.shares_tenant_as_manager_pm(auth.uid(), _user_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'user status access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS (SELECT 1 FROM public.profiles WHERE id = _user_id AND coalesce(active,true) = true);\nEND;\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"is_user_active_in_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_user_active_in_tenant(_user_id uuid, _tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT (auth.uid() = _user_id AND coalesce(public.is_tenant_member(auth.uid(), _tenant_id), false))\n         AND NOT coalesce(public.is_manager_or_higher(auth.uid(), _tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant user status access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.profiles p\n    JOIN public.user_tenant_memberships m ON m.user_id = p.id\n    WHERE p.id = _user_id AND m.tenant_id = _tenant_id\n      AND coalesce(p.active,true) = true AND coalesce(m.status,'active') = 'active'\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _tenant_id uuid"},{"name":"is_user_comped","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_user_comped(_user_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         auth.uid() IS DISTINCT FROM _user_id\n         AND NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT EXISTS (\n           SELECT 1 FROM public.user_tenant_memberships m\n           WHERE m.user_id = _user_id AND m.status = 'active'\n             AND coalesce(public.is_admin_or_higher(auth.uid(), m.tenant_id), false)\n         )\n       )\n     ) THEN\n    RAISE EXCEPTION 'user billing access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS (\n    SELECT 1 FROM public.billing_comps c\n    WHERE c.is_active = true AND (c.expires_at IS NULL OR c.expires_at > now())\n      AND ((c.scope='user' AND c.user_id=_user_id)\n        OR (c.scope='tenant' AND c.tenant_id IN (\n          SELECT tenant_id FROM public.user_tenant_memberships WHERE user_id=_user_id\n        )))\n  );\nEND;\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"is_within_business_hours","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_within_business_hours(_profile_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_tenant_id uuid;\n  v_tz text;\n  v_hours jsonb;\n  v_local timestamptz;\n  v_dow text;\n  v_today date;\n  v_override record;\n  v_day jsonb;\n  v_open time;\n  v_close time;\n  v_now_time time;\nBEGIN\n  SELECT tenant_org_id, timezone, business_hours\n    INTO v_tenant_id, v_tz, v_hours\n  FROM public.inbound_routing_profiles\n  WHERE id = _profile_id;\n\n  IF v_tenant_id IS NULL THEN RETURN false; END IF;\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(auth.uid(), v_tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'routing profile access denied' USING ERRCODE = '42501';\n  END IF;\n  IF v_tz IS NULL THEN RETURN false; END IF;\n\n  v_local := now() AT TIME ZONE v_tz;\n  v_today := v_local::date;\n  v_now_time := v_local::time;\n\n  SELECT * INTO v_override FROM public.business_hours_overrides\n   WHERE routing_profile_id = _profile_id AND override_date = v_today LIMIT 1;\n  IF FOUND THEN\n    IF v_override.closed THEN RETURN false; END IF;\n    RETURN v_now_time BETWEEN v_override.open_time AND v_override.close_time;\n  END IF;\n\n  v_dow := lower(to_char(v_local, 'dy'));\n  v_day := v_hours -> v_dow;\n  IF v_day IS NULL OR (v_day ->> 'closed')::boolean = true THEN RETURN false; END IF;\n  v_open := (v_day ->> 'open')::time;\n  v_close := (v_day ->> 'close')::time;\n  RETURN v_now_time BETWEEN v_open AND v_close;\nEND;\n$function$\n","identity_arguments":"_profile_id uuid"},{"name":"is_workflow_template_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.is_workflow_template_admin(_user_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT public.is_system_admin(_user_id);\n$function$\n","identity_arguments":"_user_id uuid"},{"name":"issue_auto_unlock_upload_ticket","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.issue_auto_unlock_upload_ticket(p_ip_hash text, p_proof_kind text, p_file_name text, p_mime text, p_size bigint)\n RETURNS TABLE(ticket_id uuid, object_path text, expires_at timestamp with time zone)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_catalog', 'pg_temp'\nAS $function$\nDECLARE\n  v_id uuid := gen_random_uuid();\n  v_ext text;\n  v_path text;\n  v_expires timestamptz := now() + interval '15 minutes';\n  v_recent integer;\n  v_daily integer;\nBEGIN\n  IF coalesce(auth.role(),'') <> 'service_role' THEN\n    RAISE EXCEPTION 'service role required' USING ERRCODE='42501';\n  END IF;\n  IF p_ip_hash !~ '^[0-9a-f]{64}$' OR p_proof_kind NOT IN ('identity','authority') THEN\n    RAISE EXCEPTION 'invalid upload ticket request' USING ERRCODE='22023';\n  END IF;\n  IF p_size IS NULL OR p_size <= 0 OR p_size > 10485760 THEN\n    RAISE EXCEPTION 'upload_size_invalid' USING ERRCODE='22023';\n  END IF;\n  v_ext := CASE p_mime\n    WHEN 'image/jpeg' THEN 'jpg'\n    WHEN 'image/png' THEN 'png'\n    WHEN 'image/webp' THEN 'webp'\n    WHEN 'image/heic' THEN 'heic'\n    WHEN 'image/heif' THEN 'heif'\n    WHEN 'application/pdf' THEN 'pdf'\n    ELSE NULL\n  END;\n  IF v_ext IS NULL OR length(coalesce(p_file_name,'')) < 1 OR length(p_file_name) > 180 THEN\n    RAISE EXCEPTION 'upload_type_invalid' USING ERRCODE='22023';\n  END IF;\n\n  PERFORM pg_advisory_xact_lock(hashtextextended(p_ip_hash, 0));\n  SELECT count(*) INTO v_recent FROM public.auto_unlock_upload_tickets\n   WHERE ip_hash=p_ip_hash AND created_at >= now()-interval '10 minutes';\n  SELECT count(*) INTO v_daily FROM public.auto_unlock_upload_tickets\n   WHERE ip_hash=p_ip_hash AND created_at >= now()-interval '24 hours';\n  IF v_recent >= 6 OR v_daily >= 20 THEN\n    RAISE EXCEPTION 'upload_rate_limited' USING ERRCODE='P0001';\n  END IF;\n\n  v_path := format('public-intake/%s/%s.%s',p_proof_kind,v_id,v_ext);\n  INSERT INTO public.auto_unlock_upload_tickets(id,object_path,proof_kind,declared_filename,declared_mime,declared_size,ip_hash,expires_at)\n  VALUES(v_id,v_path,p_proof_kind,left(p_file_name,180),p_mime,p_size,p_ip_hash,v_expires);\n  RETURN QUERY SELECT v_id,v_path,v_expires;\nEND;\n$function$\n","identity_arguments":"p_ip_hash text, p_proof_kind text, p_file_name text, p_mime text, p_size bigint"},{"name":"job_activity_set_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.job_activity_set_tenant()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.tenant_id IS NULL THEN\n    SELECT tenant_id INTO NEW.tenant_id FROM public.jobs WHERE id = NEW.job_id;\n  END IF;\n  RETURN NEW;\nEND $function$\n","identity_arguments":""},{"name":"job_photos_set_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.job_photos_set_tenant()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.tenant_id IS NULL THEN\n    SELECT tenant_id INTO NEW.tenant_id FROM public.jobs WHERE id = NEW.job_id;\n  END IF;\n  RETURN NEW;\nEND $function$\n","identity_arguments":""},{"name":"jobs_contact_claim_link_check","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.jobs_contact_claim_link_check()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_claim_contact_text text; v_claim_tenant_text text;\n  v_claim_contact_uuid uuid; v_claim_tenant_uuid uuid;\nBEGIN\n  IF NEW.contact_claim_id IS NULL THEN RETURN NEW; END IF;\n  SELECT contact_id, tenant_org_id INTO v_claim_contact_text, v_claim_tenant_text\n    FROM public.contact_claims WHERE id = NEW.contact_claim_id;\n  IF NOT FOUND THEN\n    RAISE EXCEPTION 'jobs.contact_claim_id %: claim not found', NEW.contact_claim_id USING ERRCODE='23503';\n  END IF;\n  BEGIN\n    v_claim_contact_uuid := v_claim_contact_text::uuid;\n    v_claim_tenant_uuid  := v_claim_tenant_text::uuid;\n  EXCEPTION WHEN others THEN\n    RAISE EXCEPTION 'jobs.contact_claim_id %: claim has non-uuid contact/tenant identifiers', NEW.contact_claim_id USING ERRCODE='23514';\n  END;\n  IF NEW.contact_id IS NULL OR v_claim_contact_uuid <> NEW.contact_id THEN\n    RAISE EXCEPTION 'jobs.contact_claim_id %: claim contact (%) does not match job contact (%)',\n      NEW.contact_claim_id, v_claim_contact_uuid, NEW.contact_id USING ERRCODE='23514';\n  END IF;\n  IF v_claim_tenant_uuid <> NEW.tenant_id THEN\n    RAISE EXCEPTION 'jobs.contact_claim_id %: claim tenant (%) does not match job tenant (%)',\n      NEW.contact_claim_id, v_claim_tenant_uuid, NEW.tenant_id USING ERRCODE='23514';\n  END IF;\n  RETURN NEW;\nEND; $function$\n","identity_arguments":""},{"name":"jobs_set_job_number","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.jobs_set_job_number()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.job_number IS NULL OR NEW.job_number = '' THEN\n    NEW.job_number := 'J-' || to_char(now(),'YYYYMMDD') || '-' || lpad(((random()*9999)::int)::text, 4, '0');\n  END IF;\n  RETURN NEW;\nEND $function$\n","identity_arguments":""},{"name":"jobs_set_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.jobs_set_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN NEW.updated_at = now(); RETURN NEW; END $function$\n","identity_arguments":""},{"name":"kl_is_real_tenant_media_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_is_real_tenant_media_tenant(p_tenant_id uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(auth.uid(), p_tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant media scope access denied' USING ERRCODE = '42501';\n  END IF;\n  RETURN EXISTS(\n    SELECT 1 FROM public.tenants t\n    WHERE t.id = p_tenant_id AND t.status = 'active'\n      AND coalesce(t.settings->>'storage_scope','') <> 'demo'\n      AND coalesce(t.settings->>'workspace_mode','') <> 'prospect_demo'\n      AND coalesce((t.settings->>'internal_prospect_demo')::boolean,false) = false\n  );\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"kl_proposal_version_content_immutable","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_proposal_version_content_immutable()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nbegin\n  if new.proposal_id is distinct from old.proposal_id or new.tenant_id is distinct from old.tenant_id or new.version is distinct from old.version or new.reason is distinct from old.reason or new.snapshot is distinct from old.snapshot or new.snapshot_hash is distinct from old.snapshot_hash or new.created_by is distinct from old.created_by or new.created_at is distinct from old.created_at then\n    raise exception 'proposal_version_content_is_immutable' using errcode='55000';\n  end if;\n  if old.render_hash is not null and (new.render_hash is distinct from old.render_hash or new.render_path is distinct from old.render_path or new.render_bucket is distinct from old.render_bucket) then\n    raise exception 'proposal_version_render_receipt_is_immutable' using errcode='55000';\n  end if;\n  return new;\nend; $function$\n","identity_arguments":""},{"name":"kl_refresh_tenant_media_primaries","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_refresh_tenant_media_primaries(p_tenant_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'storage', 'pg_temp'\nAS $function$\ndeclare v_logo public.tenant_media_assets%rowtype; v_background public.tenant_media_assets%rowtype; v_media_branding jsonb;\nbegin\n  if not public.kl_is_real_tenant_media_tenant(p_tenant_id) then return; end if;\n  perform pg_advisory_xact_lock(hashtextextended('prehistoric-001:'||p_tenant_id::text,0));\n  update public.tenant_media_assets set is_primary=false\n   where tenant_id=p_tenant_id and collection_key in('branding','backgrounds') and deleted_at is null and is_primary=true;\n  select * into v_logo from public.tenant_media_assets\n   where tenant_id=p_tenant_id and collection_key='branding' and deleted_at is null and status='ready'\n     and public.kl_tenant_media_mime(coalesce(storage_key,original_key),coalesce(mime_type,original_content_type,'')) like 'image/%'\n   order by coalesce(nullif(metadata->>'storage_updated_at','')::timestamptz,updated_at,created_at) desc,coalesce(storage_key,original_key) desc,id desc limit 1;\n  if v_logo.id is not null then update public.tenant_media_assets set is_primary=true where id=v_logo.id; end if;\n  select * into v_background from public.tenant_media_assets\n   where tenant_id=p_tenant_id and collection_key='backgrounds' and deleted_at is null and status='ready'\n     and public.kl_tenant_media_mime(coalesce(storage_key,original_key),coalesce(mime_type,original_content_type,'')) like 'image/%'\n   order by coalesce(nullif(metadata->>'storage_updated_at','')::timestamptz,updated_at,created_at) desc,coalesce(storage_key,original_key) desc,id desc limit 1;\n  if v_background.id is not null then update public.tenant_media_assets set is_primary=true where id=v_background.id; end if;\n  select coalesce(settings->'media_branding','{}'::jsonb) into v_media_branding from public.tenants where id=p_tenant_id for update;\n  if not found then return; end if;\n  v_media_branding:=v_media_branding||jsonb_build_object(\n    'resolved_logo_asset_id',case when v_logo.id is null then null else v_logo.id::text end,\n    'resolved_logo_version',case when v_logo.id is null then null else coalesce(v_logo.metadata->>'storage_updated_at',v_logo.updated_at::text) end,\n    'resolved_background_asset_id',case when v_background.id is null then null else v_background.id::text end,\n    'resolved_background_version',case when v_background.id is null then null else coalesce(v_background.metadata->>'storage_updated_at',v_background.updated_at::text) end,\n    'contract','PREHISTORIC-001-TENANT-MEDIA');\n  update public.tenants set settings=jsonb_set(coalesce(settings,'{}'::jsonb),'{media_branding}',v_media_branding,true),updated_at=now() where id=p_tenant_id;\nend; $function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"kl_sync_tenant_media_storage_object","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_sync_tenant_media_storage_object()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'storage', 'pg_temp'\nAS $function$\ndeclare v_object storage.objects%rowtype; v_tenant_id uuid; v_old_tenant_id uuid; v_collection text; v_mime text; v_size bigint;\nbegin\n  if tg_op='DELETE' then\n    select t.id into v_old_tenant_id from public.tenants t\n     where t.status='active' and old.bucket_id='tenant-'||t.id::text and public.kl_is_real_tenant_media_tenant(t.id) limit 1;\n    if v_old_tenant_id is not null then\n      update public.tenant_media_assets set deleted_at=now(),published=false,is_primary=false,updated_at=now()\n       where tenant_id=v_old_tenant_id and bucket_name=old.bucket_id and original_key=old.name and deleted_at is null;\n      perform public.kl_refresh_tenant_media_primaries(v_old_tenant_id);\n    end if;\n    return old;\n  end if;\n  if tg_op='UPDATE' and (old.bucket_id is distinct from new.bucket_id or old.name is distinct from new.name) then\n    select t.id into v_old_tenant_id from public.tenants t\n     where t.status='active' and old.bucket_id='tenant-'||t.id::text and public.kl_is_real_tenant_media_tenant(t.id) limit 1;\n    if v_old_tenant_id is not null then\n      update public.tenant_media_assets set deleted_at=now(),published=false,is_primary=false,updated_at=now()\n       where tenant_id=v_old_tenant_id and bucket_name=old.bucket_id and original_key=old.name and deleted_at is null;\n      perform public.kl_refresh_tenant_media_primaries(v_old_tenant_id);\n    end if;\n  end if;\n  v_object:=new;\n  select t.id into v_tenant_id from public.tenants t\n   where t.status='active' and v_object.bucket_id='tenant-'||t.id::text and public.kl_is_real_tenant_media_tenant(t.id) limit 1;\n  if v_tenant_id is null then return new; end if;\n  v_mime:=public.kl_tenant_media_mime(v_object.name,coalesce(v_object.metadata->>'mimetype',v_object.metadata->>'contentType',''));\n  if not public.kl_tenant_media_supported(v_object.name,v_mime) then return new; end if;\n  v_collection:=public.kl_tenant_media_collection(v_object.name); if coalesce(v_collection,'')='' then return new; end if;\n  begin v_size:=nullif(coalesce(v_object.metadata->>'size',v_object.metadata->>'contentLength',''),'')::bigint; exception when invalid_text_representation then v_size:=null; end;\n  insert into public.tenant_media_assets(tenant_id,collection_key,bucket_name,original_key,original_content_type,source_kind,status,review_status,published,is_primary,title,mime_type,size_bytes,storage_provider,storage_key,deleted_at,metadata,created_at,updated_at)\n  values(v_tenant_id,v_collection,v_object.bucket_id,v_object.name,nullif(v_mime,''),'existing','ready','approved',true,false,split_part(v_object.name,'/',array_length(string_to_array(v_object.name,'/'),1)),nullif(v_mime,''),v_size,'supabase',v_object.name,null,jsonb_build_object('existing_storage',true,'existing_origin','supabase_storage','source_bucket',v_object.bucket_id,'storage_object_id',v_object.id::text,'storage_created_at',v_object.created_at::text,'storage_updated_at',v_object.updated_at::text,'contract','PREHISTORIC-001-TENANT-MEDIA'),coalesce(v_object.created_at,now()),coalesce(v_object.updated_at,now()))\n  on conflict(tenant_id,bucket_name,original_key) do update set collection_key=excluded.collection_key,original_content_type=excluded.original_content_type,status='ready',review_status='approved',published=true,mime_type=excluded.mime_type,size_bytes=excluded.size_bytes,storage_provider='supabase',storage_key=excluded.storage_key,deleted_at=null,metadata=coalesce(tenant_media_assets.metadata,'{}'::jsonb)||excluded.metadata,updated_at=excluded.updated_at;\n  perform public.kl_refresh_tenant_media_primaries(v_tenant_id); return new;\nend; $function$\n","identity_arguments":""},{"name":"kl_tenant_media_collection","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_tenant_media_collection(p_name text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  select case lower(split_part(coalesce(p_name,''), '/', 1))\n    when 'logo' then 'branding'\n    when 'branding' then 'branding'\n    when 'background' then 'backgrounds'\n    when 'backgrounds' then 'backgrounds'\n    when 'video' then 'videos'\n    when 'videos' then 'videos'\n    when 'advertisement' then 'marketing'\n    when 'advertisements' then 'marketing'\n    when 'marketing' then 'marketing'\n    else trim(both '-' from regexp_replace(lower(split_part(coalesce(p_name,''), '/', 1)), '[^a-z0-9]+', '-', 'g'))\n  end;\n$function$\n","identity_arguments":"p_name text"},{"name":"kl_tenant_media_mime","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_tenant_media_mime(p_name text, p_mime text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  select case\n    when nullif(trim(coalesce(p_mime,'')),'') is not null then trim(p_mime)\n    when coalesce(p_name,'') ~* '\\.png$' then 'image/png'\n    when coalesce(p_name,'') ~* '\\.jpe?g$' then 'image/jpeg'\n    when coalesce(p_name,'') ~* '\\.webp$' then 'image/webp'\n    when coalesce(p_name,'') ~* '\\.gif$' then 'image/gif'\n    when coalesce(p_name,'') ~* '\\.svg$' then 'image/svg+xml'\n    when coalesce(p_name,'') ~* '\\.avif$' then 'image/avif'\n    when coalesce(p_name,'') ~* '\\.(mp4|m4v)$' then 'video/mp4'\n    when coalesce(p_name,'') ~* '\\.mov$' then 'video/quicktime'\n    when coalesce(p_name,'') ~* '\\.webm$' then 'video/webm'\n    else '' end;\n$function$\n","identity_arguments":"p_name text, p_mime text"},{"name":"kl_tenant_media_supported","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.kl_tenant_media_supported(p_name text, p_mime text)\n RETURNS boolean\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  select coalesce(p_name,'') !~* '(^|/)\\.keep$'\n    and public.kl_tenant_media_mime(p_name,p_mime) ~* '^(image|video)/';\n$function$\n","identity_arguments":"p_name text, p_mime text"},{"name":"knocklaunch_remove_orphan_profile_email_conflict","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.knocklaunch_remove_orphan_profile_email_conflict()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\nDECLARE\n  orphan_id uuid;\nBEGIN\n  IF NEW.email IS NULL OR btrim(NEW.email) = '' THEN\n    RETURN NEW;\n  END IF;\n\n  SELECT p.id\n    INTO orphan_id\n  FROM public.profiles p\n  WHERE lower(btrim(p.email)) = lower(btrim(NEW.email))\n    AND p.id <> NEW.id\n    AND NOT EXISTS (\n      SELECT 1\n      FROM auth.users au\n      WHERE au.id = p.id\n    )\n  LIMIT 1;\n\n  IF orphan_id IS NOT NULL THEN\n    UPDATE public.tenants SET owner_id = NULL WHERE owner_id = orphan_id;\n    DELETE FROM public.user_roles WHERE user_id = orphan_id;\n    DELETE FROM public.user_tenant_memberships WHERE user_id = orphan_id;\n    DELETE FROM public.profiles WHERE id = orphan_id;\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"knocklaunch_sync_auth_delete_to_profile","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.knocklaunch_sync_auth_delete_to_profile()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\nBEGIN\n  DELETE FROM public.profiles WHERE id = OLD.id;\n  RETURN OLD;\nEND;\n$function$\n","identity_arguments":""},{"name":"knocklaunch_sync_profile_delete_to_auth","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.knocklaunch_sync_profile_delete_to_auth()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\nBEGIN\n  DELETE FROM auth.users WHERE id = OLD.id;\n  RETURN OLD;\nEND;\n$function$\n","identity_arguments":""},{"name":"limit_for_entitlement","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.limit_for_entitlement(_tenant_id uuid, _feature_key text)\n RETURNS bigint\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.is_tenant_member(auth.uid(), _tenant_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'tenant entitlement limit access denied' USING ERRCODE = '42501';\n  END IF;\n  IF public.is_tenant_comped(_tenant_id) THEN RETURN NULL; END IF;\n  RETURN (\n    SELECT pf.limit_value\n    FROM public.tenant_subscriptions ts\n    JOIN public.plan_features pf ON pf.plan_id = ts.plan_id\n    WHERE ts.tenant_id = _tenant_id AND pf.feature_key = _feature_key\n    LIMIT 1\n  );\nEND;\n$function$\n","identity_arguments":"_tenant_id uuid, _feature_key text"},{"name":"link_job_to_claim","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.link_job_to_claim(_job_id uuid, _claim_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant      uuid;\n  v_prev_claim  uuid;\n  v_actor_email text;\nBEGIN\n  IF auth.uid() IS NULL THEN RAISE EXCEPTION 'unauthenticated' USING ERRCODE='42501'; END IF;\n\n  SELECT tenant_id, contact_claim_id INTO v_tenant, v_prev_claim\n  FROM public.jobs WHERE id = _job_id;\n\n  IF v_tenant IS NULL THEN RAISE EXCEPTION 'job not found' USING ERRCODE='02000'; END IF;\n\n  IF NOT public._is_manager_or_higher_in_tenant(v_tenant) THEN\n    RAISE EXCEPTION 'forbidden' USING ERRCODE='42501';\n  END IF;\n\n  UPDATE public.jobs SET contact_claim_id = _claim_id WHERE id = _job_id;\n\n  SELECT email INTO v_actor_email FROM auth.users WHERE id = auth.uid();\n\n  INSERT INTO public.job_activity_log\n    (job_id, tenant_id, activity_type, actor_id, actor_email, description, metadata)\n  VALUES (\n    _job_id,\n    v_tenant,\n    'job_claim_link',\n    auth.uid(),\n    v_actor_email,\n    CASE\n      WHEN v_prev_claim IS NULL THEN 'Linked job to claim'\n      WHEN v_prev_claim = _claim_id THEN 'Re-linked job to same claim'\n      ELSE 'Re-linked job to different claim'\n    END,\n    jsonb_build_object(\n      'action', 'link',\n      'previous_claim_id', v_prev_claim,\n      'new_claim_id', _claim_id\n    )\n  );\nEND; $function$\n","identity_arguments":"_job_id uuid, _claim_id uuid"},{"name":"list_jobs_with_claim_payment_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.list_jobs_with_claim_payment_status(_tenant_id uuid)\n RETURNS TABLE(claim_payment_status claim_payment_lifecycle_v4, job_count bigint)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF auth.uid() IS NULL THEN RAISE EXCEPTION 'unauthenticated' USING ERRCODE='42501'; END IF;\n  IF NOT public._is_manager_or_higher_in_tenant(_tenant_id) THEN\n    RAISE EXCEPTION 'forbidden' USING ERRCODE='42501';\n  END IF;\n  RETURN QUERY\n    SELECT cc.claim_payment_status, COUNT(*)::bigint\n    FROM public.jobs j JOIN public.contact_claims cc ON cc.id = j.contact_claim_id\n    WHERE j.tenant_id = _tenant_id AND j.contact_claim_id IS NOT NULL\n    GROUP BY cc.claim_payment_status;\nEND; $function$\n","identity_arguments":"_tenant_id uuid"},{"name":"live_edit_operations_safe","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.live_edit_operations_safe(_operations jsonb)\n RETURNS boolean\n LANGUAGE plpgsql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$ declare _operation jsonb;_action text;_component_key text;_property_key text;_property_name text;_value text;_device text; begin if _operations is null or jsonb_typeof(_operations)<>'array' or jsonb_array_length(_operations)>200 then return false;end if;for _operation in select value from jsonb_array_elements(_operations) loop if jsonb_typeof(_operation)<>'object' then return false;end if;_action:=coalesce(_operation->>'action','');_component_key:=coalesce(_operation#>>'{audit,componentKey}','');_property_key:=coalesce(_operation#>>'{audit,propertyKey}','');_value:=coalesce(_operation->>'value','');_device:=coalesce(_operation->>'device','all');if _action not in('text','visibility','order','style','attribute') or coalesce(_operation#>>'{audit,source}','')<>'live-edit' or _component_key!~'^[A-Za-z0-9_.:-]{1,120}$' or _property_key!~'^[A-Za-z0-9_.:-]{1,120}$' or length(_value)>16000 or _device not in('all','desktop','mobile') then return false;end if;if _action='text' and not(_property_key='self' or _property_key~'^text\\.[0-9]+$') then return false;end if;if _action='visibility' and _property_key<>'visibility' then return false;end if;if _action='order' and _property_key<>'order' then return false;end if;if _action='style' then if _property_key!~'^style\\.[0-9]+\\.[A-Za-z0-9-]+$' then return false;end if;_property_name:=regexp_replace(_property_key,'^style\\.[0-9]+\\.','');if _property_name not in('color','backgroundColor','opacity','borderColor','borderWidth','borderStyle','borderRadius','boxShadow','width','height','minWidth','maxWidth','minHeight','maxHeight','padding','margin','gap','fontSize','fontWeight','lineHeight','letterSpacing','textAlign','display','flexDirection','justifyContent','alignItems','objectFit','overflow') then return false;end if;end if;if _action='attribute' then if _property_key!~'^attr\\.[0-9]+\\.[A-Za-z0-9-]+$' then return false;end if;_property_name:=regexp_replace(_property_key,'^attr\\.[0-9]+\\.','');if _property_name not in('href','target','src','alt','title','aria-label') then return false;end if;if _property_name in('href','src') and _value<>'' and _value!~*'^(https?:|mailto:|tel:|/|#|data:image/)' then return false;end if;if _property_name='target' and _value not in('','_self','_blank') then return false;end if;end if;end loop;return true;end;$function$\n","identity_arguments":"_operations jsonb"},{"name":"log_activity_timeline","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_activity_timeline(p_tenant_org_id uuid, p_contact_id uuid, p_user_id uuid, p_activity_type text, p_title text, p_description text DEFAULT NULL::text, p_metadata jsonb DEFAULT '{}'::jsonb, p_related_entity_type text DEFAULT NULL::text, p_related_entity_id uuid DEFAULT NULL::uuid, p_importance text DEFAULT 'normal'::text, p_is_system boolean DEFAULT false)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_id UUID;\nBEGIN\n  INSERT INTO public.activity_timeline (\n    tenant_org_id, contact_id, user_id, activity_type, title, \n    description, metadata, related_entity_type, related_entity_id,\n    importance, is_system_generated\n  ) VALUES (\n    p_tenant_org_id, p_contact_id, p_user_id, p_activity_type, p_title,\n    p_description, p_metadata, p_related_entity_type, p_related_entity_id,\n    p_importance, p_is_system\n  ) RETURNING id INTO v_id;\n  \n  RETURN v_id;\nEND;\n$function$\n","identity_arguments":"p_tenant_org_id uuid, p_contact_id uuid, p_user_id uuid, p_activity_type text, p_title text, p_description text, p_metadata jsonb, p_related_entity_type text, p_related_entity_id uuid, p_importance text, p_is_system boolean"},{"name":"log_audit_event","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_audit_event(p_user_id uuid DEFAULT NULL::uuid, p_user_email text DEFAULT NULL::text, p_user_name text DEFAULT NULL::text, p_tenant_id uuid DEFAULT NULL::uuid, p_event_type text DEFAULT 'system'::text, p_event_category text DEFAULT 'system'::text, p_event_action text DEFAULT 'unknown'::text, p_resource_type text DEFAULT NULL::text, p_resource_id text DEFAULT NULL::text, p_resource_name text DEFAULT NULL::text, p_old_value jsonb DEFAULT NULL::jsonb, p_new_value jsonb DEFAULT NULL::jsonb, p_metadata jsonb DEFAULT '{}'::jsonb, p_ip_address text DEFAULT NULL::text, p_user_agent text DEFAULT NULL::text, p_session_id text DEFAULT NULL::text, p_success boolean DEFAULT true, p_error_message text DEFAULT NULL::text, p_severity text DEFAULT 'info'::text)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_log_id uuid;\n  v_request_user uuid := public.request_user_id();\n  v_claims text := nullif(current_setting('request.jwt.claims', true), '');\n  v_role text := nullif(current_setting('request.jwt.claim.role', true), '');\n  v_request_email text;\n  v_platform_admin boolean := false;\nbegin\n  if v_claims is not null then\n    v_role := coalesce(v_role, nullif((v_claims::jsonb) ->> 'role', ''));\n    v_request_email := nullif((v_claims::jsonb) ->> 'email', '');\n  end if;\n\n  if coalesce(v_role, '') <> 'service_role' then\n    if v_request_user is null then\n      raise exception 'authenticated audit caller required'\n        using errcode = '42501';\n    end if;\n\n    v_platform_admin := coalesce(public.is_platform_admin(v_request_user), false);\n\n    if p_user_id is not null\n       and p_user_id <> v_request_user\n       and not v_platform_admin then\n      raise exception 'audit user mismatch'\n        using errcode = '42501';\n    end if;\n\n    if p_tenant_id is not null\n       and not v_platform_admin\n       and not coalesce(public.is_tenant_member(v_request_user, p_tenant_id), false) then\n      raise exception 'audit tenant access denied'\n        using errcode = '42501';\n    end if;\n\n    if not v_platform_admin or p_user_id is null then\n      p_user_id := v_request_user;\n    end if;\n    p_user_email := coalesce(v_request_email, p_user_email);\n  end if;\n\n  insert into public.comprehensive_audit_logs (\n    user_id, user_email, user_name, tenant_id,\n    event_type, event_category, event_action,\n    resource_type, resource_id, resource_name,\n    old_value, new_value, metadata,\n    ip_address, user_agent, session_id,\n    success, error_message, severity,\n    request_id\n  ) values (\n    p_user_id, p_user_email, p_user_name, p_tenant_id,\n    p_event_type, p_event_category, p_event_action,\n    p_resource_type, p_resource_id, p_resource_name,\n    p_old_value, p_new_value, p_metadata,\n    p_ip_address, p_user_agent, p_session_id,\n    p_success, p_error_message, p_severity,\n    gen_random_uuid()::text\n  )\n  returning id into v_log_id;\n\n  return v_log_id;\nend;\n$function$\n","identity_arguments":"p_user_id uuid, p_user_email text, p_user_name text, p_tenant_id uuid, p_event_type text, p_event_category text, p_event_action text, p_resource_type text, p_resource_id text, p_resource_name text, p_old_value jsonb, p_new_value jsonb, p_metadata jsonb, p_ip_address text, p_user_agent text, p_session_id text, p_success boolean, p_error_message text, p_severity text"},{"name":"log_call_attempt","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_call_attempt(p_tenant_id text, p_lead_id text, p_phone text, p_phone_normalized text, p_rep_id uuid, p_attempt_type text, p_outcome text DEFAULT NULL::text, p_was_inbound boolean DEFAULT false, p_call_log_id uuid DEFAULT NULL::uuid)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE v_id UUID;\nBEGIN\n  INSERT INTO public.call_attempts_log (tenant_org_id, lead_id, phone_number, phone_normalized, rep_id, attempt_type, outcome, was_inbound, call_log_id)\n  VALUES (p_tenant_id, p_lead_id, p_phone, p_phone_normalized, p_rep_id, p_attempt_type, p_outcome, p_was_inbound, p_call_log_id)\n  RETURNING id INTO v_id;\n  RETURN v_id;\nEND; $function$\n","identity_arguments":"p_tenant_id text, p_lead_id text, p_phone text, p_phone_normalized text, p_rep_id uuid, p_attempt_type text, p_outcome text, p_was_inbound boolean, p_call_log_id uuid"},{"name":"log_comm_mode_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_comm_mode_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF OLD.mode IS DISTINCT FROM NEW.mode THEN\n    INSERT INTO public.mode_change_log (from_mode, to_mode, reason, changed_by, changed_by_email)\n    VALUES (OLD.mode, NEW.mode, NEW.reason, NEW.updated_by, NEW.updated_by_email);\n  END IF;\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"log_realtor_assignment_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_realtor_assignment_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant_uuid uuid;\nBEGIN\n  -- Only act on realtor tenants\n  IF NEW.tenant_org_id IS NULL OR NOT public.is_realtor_tenant(NEW.tenant_org_id) THEN\n    RETURN NEW;\n  END IF;\n\n  IF COALESCE(NEW.assigned_user,'') = COALESCE(OLD.assigned_user,'') THEN\n    RETURN NEW;\n  END IF;\n\n  v_tenant_uuid := public.try_cast_uuid(NEW.tenant_org_id);\n  IF v_tenant_uuid IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  INSERT INTO public.realtor_lead_assignments (\n    tenant_id, lead_id, previous_assigned_user_id, new_assigned_user_id, changed_by, reason\n  ) VALUES (\n    v_tenant_uuid,\n    NEW.id,\n    public.try_cast_uuid(OLD.assigned_user),\n    public.try_cast_uuid(NEW.assigned_user),\n    auth.uid(),\n    NULL\n  );\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"log_shared_claim_claim_stage_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_shared_claim_claim_stage_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_participant RECORD;\n  v_member RECORD;\n  v_actor_name TEXT;\nBEGIN\n  IF OLD.claim_stage IS DISTINCT FROM NEW.claim_stage THEN\n    SELECT name INTO v_actor_name FROM profiles WHERE id = auth.uid() LIMIT 1;\n    \n    INSERT INTO shared_claim_activity (shared_claim_id, actor_tenant_id, actor_user_id, activity_type, field_changed, old_value, new_value, metadata)\n    VALUES (NEW.id, NEW.created_by_tenant_id, auth.uid(), 'stage_change', 'claim_stage', OLD.claim_stage, NEW.claim_stage,\n      jsonb_build_object('actor_name', v_actor_name));\n\n    FOR v_participant IN \n      SELECT scp.tenant_id FROM shared_claim_participants scp \n      WHERE scp.shared_claim_id = NEW.id AND scp.status = 'accepted'\n    LOOP\n      FOR v_member IN\n        SELECT utm.user_id FROM user_tenant_memberships utm\n        WHERE utm.tenant_id = v_participant.tenant_id AND utm.status = 'active'\n      LOOP\n        INSERT INTO notification_queue (user_id, title, message, notification_type, severity, metadata, created_at)\n        VALUES (\n          v_member.user_id,\n          'Shared Claim Stage Updated',\n          'Claim stage changed to: ' || COALESCE(NEW.claim_stage, 'Unknown'),\n          'shared_claim_update',\n          'info',\n          jsonb_build_object('shared_claim_id', NEW.id, 'field', 'claim_stage', 'new_value', NEW.claim_stage, 'actor_name', v_actor_name),\n          now()\n        );\n      END LOOP;\n    END LOOP;\n  END IF;\n  \n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"log_shared_claim_stage_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_shared_claim_stage_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_participant RECORD;\n  v_member RECORD;\n  v_actor_name TEXT;\nBEGIN\n  IF OLD.jobs_stage IS DISTINCT FROM NEW.jobs_stage THEN\n    SELECT name INTO v_actor_name FROM profiles WHERE id = auth.uid() LIMIT 1;\n    \n    -- Log activity\n    INSERT INTO shared_claim_activity (shared_claim_id, actor_tenant_id, actor_user_id, activity_type, field_changed, old_value, new_value, metadata)\n    VALUES (NEW.shared_claim_id, NEW.tenant_id, auth.uid(), 'stage_change', 'jobs_stage', OLD.jobs_stage, NEW.jobs_stage, \n      jsonb_build_object('tenant_id', NEW.tenant_id, 'actor_name', v_actor_name));\n\n    -- Notify all users in OTHER participant tenants via notification_queue\n    FOR v_participant IN \n      SELECT scp.tenant_id FROM shared_claim_participants scp \n      WHERE scp.shared_claim_id = NEW.shared_claim_id AND scp.tenant_id != NEW.tenant_id AND scp.status = 'accepted'\n    LOOP\n      FOR v_member IN\n        SELECT utm.user_id FROM user_tenant_memberships utm\n        WHERE utm.tenant_id = v_participant.tenant_id AND utm.status = 'active'\n      LOOP\n        INSERT INTO notification_queue (user_id, title, message, notification_type, severity, metadata, created_at)\n        VALUES (\n          v_member.user_id,\n          'Shared Claim Update',\n          'Partner updated job stage to: ' || COALESCE(NEW.jobs_stage, 'Unknown'),\n          'shared_claim_update',\n          'info',\n          jsonb_build_object('shared_claim_id', NEW.shared_claim_id, 'field', 'jobs_stage', 'new_value', NEW.jobs_stage, 'actor_name', v_actor_name),\n          now()\n        );\n      END LOOP;\n    END LOOP;\n  END IF;\n  \n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"log_supabase_auth_event","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_supabase_auth_event()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_ip TEXT;\nBEGIN\n  -- Try multiple metadata paths for IP\n  v_ip := COALESCE(\n    NEW.raw_app_meta_data->>'ip',\n    NEW.raw_app_meta_data->>'request_ip',\n    current_setting('request.headers', true)::json->>'x-forwarded-for',\n    current_setting('request.headers', true)::json->>'cf-connecting-ip',\n    NULL\n  );\n\n  -- Treat 'unknown' as NULL\n  IF v_ip = 'unknown' OR v_ip = '' THEN\n    v_ip := NULL;\n  END IF;\n\n  INSERT INTO public.security_events (\n    event_type, user_id, email, ip_address, user_agent, metadata, severity, success, timestamp\n  ) VALUES (\n    'auth.login', NEW.id, NEW.email, v_ip,\n    COALESCE(NEW.raw_app_meta_data->>'user_agent', NULL),\n    jsonb_build_object('provider', COALESCE(NEW.raw_app_meta_data->>'provider', 'email'), 'login_at', NEW.last_sign_in_at),\n    'low', true, NOW()\n  );\n  \n  UPDATE public.profiles SET last_login_at = NEW.last_sign_in_at WHERE id = NEW.id;\n  \n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  RAISE WARNING 'log_supabase_auth_event error: %', SQLERRM;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"log_user_activity","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.log_user_activity(p_activity_type text, p_title text, p_description text DEFAULT NULL::text, p_contact_id uuid DEFAULT NULL::uuid, p_metadata jsonb DEFAULT NULL::jsonb)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user_id UUID;\n  v_tenant_id TEXT;\n  v_activity_id UUID;\nBEGIN\n  -- Get current user\n  v_user_id := auth.uid();\n  \n  IF v_user_id IS NULL THEN\n    RAISE EXCEPTION 'Authentication required';\n  END IF;\n  \n  -- Get user's tenant from profiles or memberships\n  SELECT COALESCE(p.tenant_org_id, utm.tenant_id::text)\n  INTO v_tenant_id\n  FROM profiles p\n  LEFT JOIN user_tenant_memberships utm ON utm.user_id = p.id AND utm.status = 'active'\n  WHERE p.id = v_user_id\n  LIMIT 1;\n  \n  IF v_tenant_id IS NULL THEN\n    v_tenant_id := 'system';\n  END IF;\n  \n  -- Insert activity log\n  INSERT INTO public.activity_log (\n    user_id,\n    tenant_id,\n    activity_type,\n    title,\n    description,\n    contact_id,\n    metadata,\n    created_at\n  ) VALUES (\n    v_user_id,\n    v_tenant_id,\n    p_activity_type,\n    p_title,\n    p_description,\n    p_contact_id,\n    COALESCE(p_metadata, '{}'::jsonb),\n    NOW()\n  )\n  RETURNING id INTO v_activity_id;\n  \n  RETURN v_activity_id;\nEND;\n$function$\n","identity_arguments":"p_activity_type text, p_title text, p_description text, p_contact_id uuid, p_metadata jsonb"},{"name":"mark_courses_stale_for_action","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_courses_stale_for_action(_action_key text)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_count int;\n  v_current int;\nBEGIN\n  IF NOT is_system_admin(auth.uid()) THEN\n    RAISE EXCEPTION 'GodMode only';\n  END IF;\n  SELECT current_version INTO v_current FROM public.academy_app_actions WHERE key = _action_key;\n  UPDATE public.academy_lessons\n     SET review_status = 'stale', updated_at = now()\n   WHERE linked_action_key = _action_key\n     AND action_version < COALESCE(v_current, 1);\n  GET DIAGNOSTICS v_count = ROW_COUNT;\n  RETURN v_count;\nEND;\n$function$\n","identity_arguments":"_action_key text"},{"name":"mark_courses_stale_for_workflow","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_courses_stale_for_workflow(_workflow_key text)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE v_count int;\nBEGIN\n  IF NOT is_system_admin(auth.uid()) THEN RAISE EXCEPTION 'GodMode only'; END IF;\n  UPDATE public.academy_lessons SET review_status = 'stale', updated_at = now()\n   WHERE workflow_key = _workflow_key AND review_status = 'active';\n  GET DIAGNOSTICS v_count = ROW_COUNT;\n  RETURN v_count;\nEND;\n$function$\n","identity_arguments":"_workflow_key text"},{"name":"mark_late_deadlines","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_late_deadlines()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  -- If due_date is past and still Open, mark Late on read/write\n  IF NEW.status = 'Open' AND NEW.due_date < CURRENT_DATE THEN\n    NEW.status := 'Late';\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"mark_score_stale_on_contact_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_score_stale_on_contact_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF (\n       NEW.property_year_built  IS DISTINCT FROM OLD.property_year_built\n    OR NEW.property_square_feet IS DISTINCT FROM OLD.property_square_feet\n    OR NEW.carrier              IS DISTINCT FROM OLD.carrier\n    OR NEW.carrier_name         IS DISTINCT FROM OLD.carrier_name\n    OR NEW.is_dnc               IS DISTINCT FROM OLD.is_dnc\n    OR NEW.last_touched_at      IS DISTINCT FROM OLD.last_touched_at\n    OR NEW.zip                  IS DISTINCT FROM OLD.zip\n    OR NEW.lat                  IS DISTINCT FROM OLD.lat\n    OR NEW.lng                  IS DISTINCT FROM OLD.lng\n    OR NEW.contact_status       IS DISTINCT FROM OLD.contact_status\n  ) THEN\n    UPDATE public.lead_intelligence_scores\n    SET stale = true, stale_reason = 'contact_changed', updated_at = now()\n    WHERE subject_id = NEW.id\n      AND subject_type = 'contact'\n      AND score_type = 'stormscore'\n      AND stale = false;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"mark_scores_stale_for_contact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_scores_stale_for_contact()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF (TG_OP = 'UPDATE') THEN\n    -- Only react when fields that influence the score change.\n    IF (\n      COALESCE(NEW.status,'') IS DISTINCT FROM COALESCE(OLD.status,'')\n      OR COALESCE(NEW.contact_status,'') IS DISTINCT FROM COALESCE(OLD.contact_status,'')\n      OR COALESCE(NEW.assigned_to::text,'') IS DISTINCT FROM COALESCE(OLD.assigned_to::text,'')\n      OR COALESCE(NEW.last_touched_at::text,'') IS DISTINCT FROM COALESCE(OLD.last_touched_at::text,'')\n      OR COALESCE(NEW.roof_age,'') IS DISTINCT FROM COALESCE(OLD.roof_age,'')\n      OR COALESCE(NEW.roof_permit_finaled_date::text,'') IS DISTINCT FROM COALESCE(OLD.roof_permit_finaled_date::text,'')\n      OR COALESCE(NEW.has_recent_roof_permit,false) IS DISTINCT FROM COALESCE(OLD.has_recent_roof_permit,false)\n      OR COALESCE(NEW.permit_data::text,'') IS DISTINCT FROM COALESCE(OLD.permit_data::text,'')\n      OR COALESCE(NEW.zip,'') IS DISTINCT FROM COALESCE(OLD.zip,'')\n    ) THEN\n      UPDATE public.lead_intelligence_scores\n         SET stale = true,\n             stale_reason = 'contact_updated'\n       WHERE subject_type IN ('contact','lead','client')\n         AND subject_id = NEW.id;\n    END IF;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"mark_scores_stale_on_storm","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_scores_stale_on_storm()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.zip_prefix IS NOT NULL AND NEW.state IS NOT NULL THEN\n    UPDATE public.lead_intelligence_scores s\n    SET stale = true, stale_reason = 'new_storm_event', updated_at = now()\n    FROM public.unified_contacts c\n    WHERE s.subject_id = c.id\n      AND s.subject_type = 'contact'\n      AND s.score_type = 'stormscore'\n      AND c.deleted_at IS NULL\n      AND c.state = NEW.state\n      AND substring(c.zip from 1 for 3) = NEW.zip_prefix\n      AND s.stale = false;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"mark_scores_stale_on_storm_event","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_scores_stale_on_storm_event()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  -- New storm landed → flag every contact in the affected county as stale.\n  UPDATE public.lead_intelligence_scores lis\n     SET stale = true,\n         stale_reason = 'new_storm_event'\n    FROM public.unified_contacts uc\n   WHERE lis.subject_id = uc.id\n     AND lis.subject_type IN ('contact','lead','client')\n     AND uc.tenant_org_id = lis.tenant_org_id\n     AND (\n       (NEW.zip_prefix IS NOT NULL AND uc.zip IS NOT NULL\n          AND left(uc.zip, length(NEW.zip_prefix)) = NEW.zip_prefix)\n       OR (NEW.county IS NOT NULL AND uc.city IS NOT NULL\n            AND lower(uc.city) = lower(NEW.county))\n     );\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"mark_voicemail_read","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mark_voicemail_read(_voicemail_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE v_tenant text;\nBEGIN\n  SELECT tenant_org_id INTO v_tenant FROM voicemail_messages WHERE id = _voicemail_id;\n  IF v_tenant IS NULL THEN RAISE EXCEPTION 'Voicemail not found'; END IF;\n  IF NOT is_tenant_member(v_tenant) THEN RAISE EXCEPTION 'Not authorized'; END IF;\n  UPDATE voicemail_messages\n    SET is_read = true, read_by_user_id = auth.uid(), read_at = now()\n    WHERE id = _voicemail_id;\nEND $function$\n","identity_arguments":"_voicemail_id uuid"},{"name":"materialize_lawn_workday","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.materialize_lawn_workday(p_tenant_id uuid, p_service_date date DEFAULT CURRENT_DATE)\n RETURNS jsonb\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  generated integer := 0;\n  route_row public.lawn_service_routes%ROWTYPE;\n  visit_count integer := 0;\n  default_crew text;\nBEGIN\n  generated := public.generate_lawn_service_visits(p_tenant_id, p_service_date, 0);\n\n  SELECT item_id INTO default_crew\n  FROM public.lawn_care_readiness_items\n  WHERE tenant_id = p_tenant_id\n    AND item_type = 'crew'\n    AND status = 'Assigned'\n  ORDER BY updated_at DESC, item_id\n  LIMIT 1;\n\n  SELECT count(*) INTO visit_count\n  FROM public.lawn_service_visits\n  WHERE tenant_id = p_tenant_id\n    AND service_date = p_service_date\n    AND status <> 'cancelled';\n\n  IF visit_count > 0 THEN\n    INSERT INTO public.lawn_service_routes (tenant_id, service_date, status, assigned_crew_id, metadata)\n    VALUES (\n      p_tenant_id,\n      p_service_date,\n      'planned',\n      default_crew,\n      jsonb_build_object('materialized_by','seaside_today_v2','materialized_at',now())\n    )\n    ON CONFLICT (tenant_id, service_date) DO UPDATE\n    SET assigned_crew_id = coalesce(public.lawn_service_routes.assigned_crew_id, excluded.assigned_crew_id),\n        metadata = public.lawn_service_routes.metadata || excluded.metadata\n    RETURNING * INTO route_row;\n\n    UPDATE public.lawn_service_visits\n    SET route_id = route_row.id,\n        assigned_crew_id = coalesce(assigned_crew_id, route_row.assigned_crew_id)\n    WHERE tenant_id = p_tenant_id\n      AND service_date = p_service_date\n      AND status <> 'cancelled'\n      AND (route_id IS DISTINCT FROM route_row.id OR (assigned_crew_id IS NULL AND route_row.assigned_crew_id IS NOT NULL));\n  END IF;\n\n  RETURN jsonb_build_object(\n    'tenant_id', p_tenant_id,\n    'service_date', p_service_date,\n    'generated_visits', generated,\n    'visit_count', visit_count,\n    'route_id', route_row.id,\n    'assigned_crew_id', route_row.assigned_crew_id\n  );\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_service_date date"},{"name":"materialize_owner_notes_tasks_from_email_signal","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.materialize_owner_notes_tasks_from_email_signal()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_owner_user_id uuid;\n  v_source_id text;\n  v_summary text;\n  v_due_at timestamptz;\n  v_actionable boolean;\nbegin\n  v_source_id := 'mail:' || coalesce(nullif(new.provider, ''), 'provider') || ':' || coalesce(nullif(new.provider_message_id, ''), new.id::text);\n  v_actionable := lower(coalesce(new.status, 'review')) not in ('ignored', 'dismissed')\n    and (\n      new.classification = 'event_opportunity'\n      or jsonb_array_length(coalesce(new.proposed_actions, '[]'::jsonb)) > 0\n    );\n\n  -- A later Mail dismissal deterministically suppresses previously generated items\n  -- without deleting their stable source identity, so they cannot reappear on rescan.\n  if not v_actionable then\n    update public.tasks\n      set status = 'dismissed', updated_at = now()\n      where tenant_id = new.tenant_org_id\n        and source_kind = 'inbound_email_signal'\n        and source_id = v_source_id;\n    update public.owner_workspace_notes\n      set dismissed_at = coalesce(dismissed_at, now()), updated_at = now()\n      where tenant_id = new.tenant_org_id\n        and source_type = 'inbound_email_signal'\n        and source_id = v_source_id;\n    return new;\n  end if;\n\n  select membership.user_id\n    into v_owner_user_id\n    from public.user_tenant_memberships membership\n    where membership.tenant_id = new.tenant_org_id::uuid\n      and membership.status = 'active'\n      and membership.is_owner is true\n    order by membership.joined_at nulls last, membership.id\n    limit 1;\n\n  if v_owner_user_id is null then\n    return new;\n  end if;\n\n  v_summary := concat_ws(' • ',\n    nullif(new.sender_name, ''),\n    nullif(new.sender_email, ''),\n    nullif(new.extracted->>'event_type', ''),\n    nullif(new.extracted->>'date_text', ''),\n    nullif(new.extracted->>'time_text', ''),\n    nullif(new.extracted->>'location', ''),\n    case when nullif(new.extracted->>'guest_count', '') is not null then (new.extracted->>'guest_count') || ' guests' end\n  );\n\n  begin\n    v_due_at := nullif(new.extracted->>'event_date', '')::timestamptz;\n  exception when others then\n    v_due_at := null;\n  end;\n\n  insert into public.tasks (\n    tenant_id, user_id, title, description, priority, status, due_date, metadata\n  ) values (\n    new.tenant_org_id,\n    v_owner_user_id,\n    'Follow up: ' || coalesce(nullif(new.subject, ''), nullif(new.sender_name, ''), nullif(new.sender_email, ''), 'email'),\n    nullif(v_summary, ''),\n    'medium',\n    'pending',\n    v_due_at,\n    jsonb_build_object(\n      'auto_generated', true,\n      'source_kind', 'inbound_email_signal',\n      'source_id', v_source_id,\n      'email_signal_id', new.id,\n      'provider_message_id', new.provider_message_id,\n      'source_route', '/big-papis-coquito-iceys/owner/email'\n    )\n  ) on conflict (tenant_id, source_kind, source_id) where source_kind is not null and source_id is not null do nothing;\n\n  insert into public.owner_workspace_notes (\n    tenant_id, user_id, title, body, pinned, source_type, source_id, source_metadata\n  ) values (\n    new.tenant_org_id,\n    v_owner_user_id,\n    coalesce(nullif(new.subject, ''), 'Mail note'),\n    coalesce(nullif(v_summary, ''), 'Actionable email captured by KnockLaunch Mail.'),\n    false,\n    'inbound_email_signal',\n    v_source_id,\n    jsonb_build_object(\n      'email_signal_id', new.id,\n      'provider_message_id', new.provider_message_id,\n      'source_route', '/big-papis-coquito-iceys/owner/email'\n    )\n  ) on conflict (tenant_id, source_type, source_id) where source_type is not null and source_id is not null do nothing;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"mirror_lead_deck_to_unified","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.mirror_lead_deck_to_unified()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF TG_OP = 'INSERT' THEN\n    IF NEW.tenant_org_id IS NULL THEN\n      RETURN NEW;\n    END IF;\n\n    IF EXISTS (SELECT 1 FROM public.unified_contacts WHERE id = NEW.id) THEN\n      UPDATE public.unified_contacts SET\n        tenant_org_id = NEW.tenant_org_id,\n        name = NEW.name, phone = NEW.phone, email = NEW.email,\n        address = NEW.address, city = NEW.city, state = NEW.state, zip = NEW.zip,\n        status = NEW.status, priority = NEW.priority, source = NEW.source,\n        assigned_to = NEW.assigned_to, notes = NEW.notes,\n        lead_stage = NEW.lead_stage, graduated_at = NEW.graduated_at,\n        property_data = NEW.property_data, property_parcel_id = NEW.property_parcel_id,\n        property_owner_name = NEW.property_owner_name,\n        property_assessed_value = NEW.property_assessed_value,\n        property_square_feet = NEW.property_square_feet,\n        property_year_built = NEW.property_year_built,\n        lat = NEW.lat, lng = NEW.lng,\n        updated_at = COALESCE(NEW.updated_at, now()),\n        last_touched_at = COALESCE(NEW.updated_at, last_touched_at)\n      WHERE id = NEW.id;\n    ELSE\n      IF EXISTS (\n        SELECT 1 FROM public.unified_contacts uc\n        WHERE uc.tenant_org_id = NEW.tenant_org_id\n          AND (\n            (NULLIF(regexp_replace(coalesce(uc.phone,''),'[^0-9]','','g'),'') IS NOT NULL\n              AND regexp_replace(coalesce(uc.phone,''),'[^0-9]','','g')\n                = regexp_replace(coalesce(NEW.phone,''),'[^0-9]','','g'))\n            OR\n            (NULLIF(lower(trim(coalesce(uc.address,''))),'') IS NOT NULL\n              AND lower(trim(coalesce(uc.address,'')))\n                = lower(trim(coalesce(NEW.address,''))))\n          )\n      ) THEN\n        RETURN NEW;\n      END IF;\n\n      INSERT INTO public.unified_contacts (\n        id, tenant_org_id, legacy_lead_deck_id, lead_id, name, phone, email,\n        address, city, state, zip, status, priority, source, assigned_to,\n        notes, created_at, updated_at, last_touched_at, lead_origin, lead_stage,\n        graduated_at, property_data, property_parcel_id, property_owner_name,\n        property_assessed_value, property_square_feet, property_year_built, lat, lng\n      ) VALUES (\n        NEW.id, NEW.tenant_org_id, NEW.id, NEW.lead_id, NEW.name, NEW.phone, NEW.email,\n        NEW.address, NEW.city, NEW.state, NEW.zip, NEW.status, NEW.priority, NEW.source,\n        NEW.assigned_to, NEW.notes, COALESCE(NEW.created_at, now()),\n        COALESCE(NEW.updated_at, now()), COALESCE(NEW.updated_at, now()), 'system',\n        NEW.lead_stage, NEW.graduated_at, NEW.property_data, NEW.property_parcel_id,\n        NEW.property_owner_name, NEW.property_assessed_value, NEW.property_square_feet,\n        NEW.property_year_built, NEW.lat, NEW.lng\n      );\n    END IF;\n    RETURN NEW;\n  ELSIF TG_OP = 'UPDATE' THEN\n    UPDATE public.unified_contacts SET\n      tenant_org_id = NEW.tenant_org_id,\n      name = NEW.name, phone = NEW.phone, email = NEW.email,\n      address = NEW.address, city = NEW.city, state = NEW.state, zip = NEW.zip,\n      status = NEW.status, priority = NEW.priority, source = NEW.source,\n      assigned_to = NEW.assigned_to, notes = NEW.notes,\n      lead_stage = NEW.lead_stage, graduated_at = NEW.graduated_at,\n      property_data = NEW.property_data, property_parcel_id = NEW.property_parcel_id,\n      property_owner_name = NEW.property_owner_name,\n      property_assessed_value = NEW.property_assessed_value,\n      property_square_feet = NEW.property_square_feet,\n      property_year_built = NEW.property_year_built,\n      lat = NEW.lat, lng = NEW.lng,\n      updated_at = COALESCE(NEW.updated_at, now()),\n      last_touched_at = COALESCE(NEW.updated_at, last_touched_at)\n    WHERE id = NEW.id OR legacy_lead_deck_id = NEW.id;\n    RETURN NEW;\n  ELSIF TG_OP = 'DELETE' THEN\n    UPDATE public.unified_contacts\n    SET archived_at = now(), updated_at = now()\n    WHERE (id = OLD.id OR legacy_lead_deck_id = OLD.id)\n      AND archived_at IS NULL;\n    RETURN OLD;\n  END IF;\n  RETURN NULL;\nEND;\n$function$\n","identity_arguments":""},{"name":"move_to_dlq","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.move_to_dlq(source_queue text, dlq_name text, message_id bigint, payload jsonb)\n RETURNS bigint\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\nDECLARE new_id BIGINT;\nBEGIN\n  SELECT pgmq.send(dlq_name, payload) INTO new_id;\n  PERFORM pgmq.delete(source_queue, message_id);\n  RETURN new_id;\nEXCEPTION WHEN undefined_table THEN\n  BEGIN\n    PERFORM pgmq.create(dlq_name);\n  EXCEPTION WHEN OTHERS THEN\n    NULL;\n  END;\n  SELECT pgmq.send(dlq_name, payload) INTO new_id;\n  BEGIN\n    PERFORM pgmq.delete(source_queue, message_id);\n  EXCEPTION WHEN undefined_table THEN\n    NULL;\n  END;\n  RETURN new_id;\nEND;\n$function$\n","identity_arguments":"source_queue text, dlq_name text, message_id bigint, payload jsonb"},{"name":"next_global_lead","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.next_global_lead()\n RETURNS TABLE(id uuid, lead_id text, name text, phone text, email text, address text, city text, state text, zip text, status text, priority text, source text, assigned_to text, notes text, tenant_org_id text, created_at timestamp with time zone, updated_at timestamp with time zone)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  RETURN QUERY\n  SELECT \n    ld.id,\n    ld.lead_id,\n    ld.name,\n    ld.phone,\n    ld.email,\n    ld.address,\n    ld.city,\n    ld.state,\n    ld.zip,\n    ld.status,\n    ld.priority,\n    ld.source,\n    ld.assigned_to,\n    ld.notes,\n    ld.tenant_org_id,\n    ld.created_at,\n    ld.updated_at\n  FROM lead_deck ld\n  WHERE ld.deleted_at IS NULL\n    AND ld.tenant_org_id IS NULL\n    AND (ld.assigned_to IS NULL OR ld.assigned_to = '')\n    AND (ld.status IS NULL OR ld.status NOT IN (\n      'Completed', 'Closed', 'Lost', 'DNC', 'Suppressed', \n      'Not Qualified', 'Not Qualified - Metal'\n    ))\n  ORDER BY RANDOM()\n  LIMIT 1;\nEND;\n$function$\n","identity_arguments":""},{"name":"next_supplement_number","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.next_supplement_number(_claim_id uuid)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_next integer;\n  v_tenant_text text;\n  v_tenant_id uuid;\n  v_request_user uuid := public.request_user_id();\n  v_claims text := nullif(current_setting('request.jwt.claims', true), '');\n  v_role text := nullif(current_setting('request.jwt.claim.role', true), '');\nbegin\n  if v_claims is not null then\n    v_role := coalesce(v_role, nullif((v_claims::jsonb) ->> 'role', ''));\n  end if;\n\n  select cc.tenant_org_id\n    into v_tenant_text\n    from public.contact_claims cc\n   where cc.id = _claim_id;\n\n  if not found then\n    raise exception 'claim not found'\n      using errcode = '22023';\n  end if;\n\n  v_tenant_id := public.try_cast_uuid(v_tenant_text);\n  if v_tenant_id is null then\n    raise exception 'claim tenant is invalid'\n      using errcode = '22023';\n  end if;\n\n  if coalesce(v_role, '') <> 'service_role' then\n    if v_request_user is null\n       or (\n         not coalesce(public.is_platform_admin(v_request_user), false)\n         and not coalesce(public.is_tenant_member(v_request_user, v_tenant_id), false)\n       ) then\n      raise exception 'claim tenant access denied'\n        using errcode = '42501';\n    end if;\n  end if;\n\n  select coalesce(max(cs.supplement_number), 0) + 1\n    into v_next\n    from public.claim_supplements cs\n   where cs.claim_id = _claim_id;\n\n  return v_next;\nend;\n$function$\n","identity_arguments":"_claim_id uuid"},{"name":"next_voicemail_preset_slot","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.next_voicemail_preset_slot(_rep_id uuid, _phone text)\n RETURNS smallint\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  attempts_30d int;\nBEGIN\n  IF coalesce(auth.role(), '') <> 'service_role'\n     AND (\n       auth.uid() IS NULL\n       OR (\n         auth.uid() IS DISTINCT FROM _rep_id\n         AND NOT coalesce(public.is_system_admin(auth.uid()), false)\n         AND NOT coalesce(public.shares_tenant_as_manager_pm(auth.uid(), _rep_id), false)\n       )\n     ) THEN\n    RAISE EXCEPTION 'voicemail preset access denied' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT count(*) INTO attempts_30d\n  FROM public.call_logs\n  WHERE phone_called = _phone\n    AND created_at >= now() - interval '30 days';\n\n  IF attempts_30d >= 3 THEN RETURN NULL; END IF;\n  RETURN least(attempts_30d + 1, 3)::smallint;\nEND;\n$function$\n","identity_arguments":"_rep_id uuid, _phone text"},{"name":"normalize_address","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.normalize_address(_addr text, _zip text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT\n    CASE\n      WHEN _addr IS NULL OR length(trim(_addr)) = 0 THEN NULL\n      ELSE\n        regexp_replace(\n          regexp_replace(\n            regexp_replace(\n              lower(trim(_addr)),\n              '\\s+(street|str|st\\.?)\\b', ' st', 'g'\n            ),\n            '\\s+(avenue|ave\\.?)\\b', ' ave', 'g'\n          ),\n          '[^a-z0-9 ]', '', 'g'\n        )\n        || coalesce(' ' || substring(regexp_replace(coalesce(_zip,''), '\\D', '', 'g') from 1 for 5), '')\n    END;\n$function$\n","identity_arguments":"_addr text, _zip text"},{"name":"normalize_phone_for_dnc","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.normalize_phone_for_dnc(p text)\n RETURNS text\n LANGUAGE sql\n IMMUTABLE\n SET search_path TO 'public'\nAS $function$\n  SELECT CASE\n    WHEN p IS NULL OR length(regexp_replace(p, '[^0-9]', '', 'g')) < 10 THEN NULL\n    ELSE right(regexp_replace(p, '[^0-9]', '', 'g'), 10)\n  END;\n$function$\n","identity_arguments":"p text"},{"name":"normalize_tenant_logo_ingest_base64","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.normalize_tenant_logo_ingest_base64()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\ndeclare\n  raw_logo text;\n  normalized_logo text;\n  padding_count integer;\n  logo_mime text;\n  normalized_data_url text;\nbegin\n  if new.settings is null then\n    return new;\n  end if;\n\n  raw_logo := nullif(btrim(new.settings ->> 'logo_ingest_b64'), '');\n  logo_mime := lower(coalesce(nullif(btrim(new.settings ->> 'logo_ingest_mime'), ''), 'image/webp'));\n\n  if raw_logo is null or logo_mime not like 'image/%' then\n    return new;\n  end if;\n\n  normalized_logo := regexp_replace(raw_logo, '\\s+', '', 'g');\n  padding_count := (4 - (length(normalized_logo) % 4)) % 4;\n  if padding_count > 0 then\n    normalized_logo := normalized_logo || repeat('=', padding_count);\n  end if;\n\n  begin\n    perform decode(normalized_logo, 'base64');\n  exception when others then\n    return new;\n  end;\n\n  if normalized_logo is distinct from raw_logo then\n    new.settings := jsonb_set(new.settings, '{logo_ingest_b64}', to_jsonb(normalized_logo), true);\n  end if;\n\n  normalized_data_url := 'data:' || logo_mime || ';base64,' || normalized_logo;\n  if nullif(btrim(new.company_logo_url), '') is null or lower(new.company_logo_url) like 'data:%' then\n    new.company_logo_url := normalized_data_url;\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"notify_tenant_owner_on_appointment","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.notify_tenant_owner_on_appointment()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_owner_id UUID;\n  v_tenant_name TEXT;\nBEGIN\n  -- Only fire when lead_stage changes TO 'Appointment Set'\n  IF NEW.lead_stage = 'Appointment Set' AND (OLD.lead_stage IS DISTINCT FROM 'Appointment Set') THEN\n    \n    -- Get tenant owner\n    SELECT t.owner_id, t.name INTO v_owner_id, v_tenant_name\n    FROM tenants t\n    WHERE t.id::text = NEW.tenant_org_id\n    LIMIT 1;\n    \n    IF v_owner_id IS NOT NULL THEN\n      INSERT INTO notifications (user_id, tenant_id, type, title, message, link, metadata)\n      VALUES (\n        v_owner_id,\n        NEW.tenant_org_id::uuid,\n        'appointment_booked',\n        '🎯 New Appointment Booked!',\n        COALESCE(NEW.name, 'A lead') || ' — ' || COALESCE(NEW.appt_date, 'TBD') || ' at ' || COALESCE(NEW.appt_time, 'TBD') || ' (set by ' || COALESCE(NEW.assigned_rep, 'unknown') || ')',\n        '/clients/' || NEW.id::text,\n        jsonb_build_object(\n          'lead_id', NEW.lead_id,\n          'customer_name', NEW.name,\n          'appt_date', NEW.appt_date,\n          'appt_time', NEW.appt_time,\n          'rep', NEW.assigned_rep\n        )\n      );\n    END IF;\n  END IF;\n  \n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"notify_tenant_owners_dnc_overdue","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.notify_tenant_owners_dnc_overdue(_days_since integer)\n RETURNS integer\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\nDECLARE\n  v_count integer := 0;\n  v_tenant_count integer := 0;\n  v_platform_count integer := 0;\n  v_title text;\n  v_message text;\n  v_today date := current_date;\nBEGIN\n  v_title := CASE\n    WHEN _days_since >= 31 THEN '⚠️ Federal DNC Scrub OVERDUE'\n    ELSE 'Federal DNC Scrub Due Soon'\n  END;\n  v_message := CASE\n    WHEN _days_since >= 31 THEN 'Your last FTC DNC scrub was ' || _days_since || ' days ago. Calling workflows are blocked until an admin runs the scrub. (FTC TSR §310.4(b)(3)(iv) requires scrubs every 31 days.)'\n    ELSE 'Your last FTC DNC scrub was ' || _days_since || ' days ago. Please coordinate with an admin to re-scrub before day 31 to avoid blocked workflows.'\n  END;\n\n  -- Tenant notifications: role and active membership must be the same tenant.\n  INSERT INTO public.notifications (user_id, tenant_id, type, title, message, link, metadata)\n  SELECT DISTINCT\n    ur.user_id,\n    ur.tenant_id::text,\n    'dnc_scrub_overdue',\n    v_title,\n    v_message,\n    '/admin/dnc',\n    jsonb_build_object('days_since', _days_since, 'reminder_date', v_today)\n  FROM public.user_roles ur\n  JOIN public.user_tenant_memberships m\n    ON m.user_id = ur.user_id\n   AND m.tenant_id = ur.tenant_id\n  WHERE ur.tenant_id IS NOT NULL\n    AND m.status = 'active'\n    AND ur.role IN ('Owner','Tenant Owner','Admin')\n    AND NOT EXISTS (\n      SELECT 1 FROM public.notifications n\n      WHERE n.user_id = ur.user_id\n        AND n.tenant_id IS NOT DISTINCT FROM ur.tenant_id::text\n        AND n.type = 'dnc_scrub_overdue'\n        AND (n.metadata->>'reminder_date')::date = v_today\n    );\n  GET DIAGNOSTICS v_tenant_count = ROW_COUNT;\n\n  -- Platform notifications: strict system-admin primitive only.\n  INSERT INTO public.notifications (user_id, tenant_id, type, title, message, link, metadata)\n  SELECT DISTINCT\n    p.id,\n    NULL,\n    'dnc_scrub_overdue',\n    v_title,\n    v_message,\n    '/admin/dnc',\n    jsonb_build_object('days_since', _days_since, 'reminder_date', v_today, 'platform_admin', true)\n  FROM public.profiles p\n  WHERE public.is_system_admin(p.id)\n    AND NOT EXISTS (\n      SELECT 1 FROM public.notifications n\n      WHERE n.user_id = p.id\n        AND n.tenant_id IS NULL\n        AND n.type = 'dnc_scrub_overdue'\n        AND (n.metadata->>'reminder_date')::date = v_today\n    );\n  GET DIAGNOSTICS v_platform_count = ROW_COUNT;\n\n  v_count := v_tenant_count + v_platform_count;\n  RETURN v_count;\nEND;\n$function$\n","identity_arguments":"_days_since integer"},{"name":"owner_capture_unknown_inbound_call_contact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.owner_capture_unknown_inbound_call_contact()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_tenant uuid;\n  v_digits text;\n  v_contact_id uuid;\nbegin\n  if coalesce(new.direction, 'inbound') <> 'inbound' then\n    return new;\n  end if;\n\n  v_tenant := new.tenant_org_id;\n\n  if v_tenant is null then\n    select tenant_org_id into v_tenant\n    from public.tenant_phone_numbers\n    where phone_number = new.to_number\n      and is_active = true\n    order by is_default desc, created_at desc\n    limit 1;\n  end if;\n\n  if v_tenant is null then\n    return new;\n  end if;\n\n  new.tenant_org_id := v_tenant;\n\n  v_digits := regexp_replace(coalesce(new.from_number, ''), '\\D', '', 'g');\n\n  if length(v_digits) = 11 and left(v_digits, 1) = '1' then\n    v_digits := right(v_digits, 10);\n  end if;\n\n  if v_digits is null or length(v_digits) < 10 then\n    return new;\n  end if;\n\n  select id into v_contact_id\n  from public.unified_contacts\n  where tenant_org_id = v_tenant::text\n    and deleted_at is null\n    and (\n      phone ilike '%' || v_digits || '%'\n      or normalized_phone = v_digits\n    )\n  order by created_at desc\n  limit 1;\n\n  if v_contact_id is null then\n    insert into public.unified_contacts (\n      tenant_org_id,\n      name,\n      phone,\n      normalized_phone,\n      source,\n      import_source,\n      lead_origin,\n      lead_stage,\n      status,\n      contact_status,\n      priority,\n      raw_data,\n      is_dnc,\n      is_test_account,\n      test_account_static,\n      voicemail_attempt_count\n    )\n    values (\n      v_tenant::text,\n      'Inbound Call Lead ' || coalesce(new.from_number, v_digits),\n      v_digits,\n      v_digits,\n      'Inbound Call',\n      'inbound_call_capture_net',\n      'system',\n      'New / Unassigned',\n      'New',\n      'New',\n      'high',\n      jsonb_build_object(\n        'capture_net', 'owner-inbound-call-unknown-contact-net-v1',\n        'first_channel', 'call',\n        'from_number', new.from_number,\n        'to_number', new.to_number,\n        'twilio_call_sid', new.twilio_call_sid,\n        'call_status', new.call_status,\n        'recording_url', new.recording_url,\n        'captured_at', now()\n      ),\n      false,\n      false,\n      false,\n      0\n    )\n    returning id into v_contact_id;\n  end if;\n\n  new.raw_payload := coalesce(new.raw_payload, '{}'::jsonb)\n    || jsonb_build_object(\n      'capture_net_contact_id', v_contact_id,\n      'capture_net', 'owner-inbound-call-unknown-contact-net-v1'\n    );\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"owner_capture_unknown_inbound_sms_contact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.owner_capture_unknown_inbound_sms_contact()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_tenant uuid;\n  v_digits text;\n  v_contact_id uuid;\nbegin\n  if new.direction <> 'inbound' then\n    return new;\n  end if;\n\n  if new.contact_id is not null then\n    return new;\n  end if;\n\n  v_tenant := nullif(new.tenant_id, '00000000-0000-0000-0000-000000000000'::uuid);\n\n  if v_tenant is null then\n    select tenant_org_id into v_tenant\n    from public.tenant_phone_numbers\n    where phone_number = new.to_number\n      and is_active = true\n    order by is_default desc, created_at desc\n    limit 1;\n  end if;\n\n  if v_tenant is null then\n    new.error_message := coalesce(new.error_message, 'Unknown inbound SMS: tenant could not be resolved');\n    return new;\n  end if;\n\n  new.tenant_id := v_tenant;\n\n  v_digits := regexp_replace(coalesce(new.from_number, ''), '\\D', '', 'g');\n\n  if length(v_digits) = 11 and left(v_digits, 1) = '1' then\n    v_digits := right(v_digits, 10);\n  end if;\n\n  select id into v_contact_id\n  from public.unified_contacts\n  where tenant_org_id = v_tenant::text\n    and deleted_at is null\n    and (\n      phone ilike '%' || v_digits || '%'\n      or normalized_phone = v_digits\n    )\n  order by created_at desc\n  limit 1;\n\n  if v_contact_id is null then\n    insert into public.unified_contacts (\n      tenant_org_id,\n      name,\n      phone,\n      normalized_phone,\n      source,\n      import_source,\n      lead_origin,\n      lead_stage,\n      status,\n      contact_status,\n      priority,\n      raw_data,\n      is_dnc,\n      is_test_account,\n      test_account_static,\n      voicemail_attempt_count\n    )\n    values (\n      v_tenant::text,\n      'Inbound Lead ' || coalesce(new.from_number, v_digits),\n      v_digits,\n      v_digits,\n      'Inbound SMS',\n      'inbound_sms_capture_net',\n      'system',\n      'New / Unassigned',\n      'New',\n      'New',\n      'high',\n      jsonb_build_object(\n        'capture_net', 'owner-sms-unknown-contact-net-v2',\n        'first_channel', 'sms',\n        'from_number', new.from_number,\n        'to_number', new.to_number,\n        'body_preview', left(coalesce(new.body, ''), 240),\n        'twilio_sid', new.twilio_sid,\n        'captured_at', now()\n      ),\n      false,\n      false,\n      false,\n      0\n    )\n    returning id into v_contact_id;\n  end if;\n\n  new.contact_id := v_contact_id;\n  new.error_message := null;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"owner_sms_history_dedupe_sid_guard","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.owner_sms_history_dedupe_sid_guard()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nbegin\n  if new.twilio_sid is null or btrim(new.twilio_sid) = '' then\n    return new;\n  end if;\n\n  if exists (\n    select 1\n    from public.sms_history existing\n    where existing.twilio_sid = new.twilio_sid\n    limit 1\n  ) then\n    return null;\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"pa_lor_templates_enforce_single_default","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.pa_lor_templates_enforce_single_default()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.is_default THEN\n    UPDATE public.pa_lor_templates\n       SET is_default = false\n     WHERE tenant_org_id = NEW.tenant_org_id\n       AND id <> NEW.id\n       AND is_default = true;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"pa_lor_templates_touch","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.pa_lor_templates_touch()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN NEW.updated_at = now(); RETURN NEW; END;\n$function$\n","identity_arguments":""},{"name":"pick_next_ring_group_member","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.pick_next_ring_group_member(_group_id uuid)\n RETURNS TABLE(user_id uuid, phone text)\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT rgm.user_id::uuid,\n         coalesce(nullif(ap.current_phone,''), nullif(p.phone,''))::text\n  FROM public.ring_group_members rgm\n  JOIN public.ring_groups rg ON rg.id = rgm.ring_group_id AND rg.is_active = true\n  JOIN public.profiles p ON p.id = rgm.user_id\n  LEFT JOIN public.agent_presence ap ON ap.user_id = rgm.user_id AND ap.tenant_id = rgm.tenant_org_id\n  WHERE rgm.ring_group_id = _group_id\n    AND public.is_tenant_member(auth.uid(), rg.tenant_org_id)\n    AND rgm.is_active = true\n    AND coalesce(nullif(ap.current_phone,''), nullif(p.phone,'')) IS NOT NULL\n    AND coalesce(nullif(ap.current_phone,''), nullif(p.phone,'')) <> ''\n    AND (ap.status IS NULL OR ap.status IN ('available','online','idle'))\n  ORDER BY rgm.priority ASC NULLS LAST, rgm.user_id ASC\n  LIMIT 1;\n$function$\n","identity_arguments":"_group_id uuid"},{"name":"portal_ack_check_received","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.portal_ack_check_received(_portal_token text, _claim_id uuid, _received boolean, _notes text DEFAULT NULL::text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _link RECORD;\n  _claim RECORD;\nBEGIN\n  -- Validate portal link\n  SELECT * INTO _link FROM public.portal_links\n   WHERE token = _portal_token AND is_active = true\n     AND (expires_at IS NULL OR expires_at > now())\n   LIMIT 1;\n\n  IF _link IS NULL THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Invalid or expired portal link');\n  END IF;\n\n  -- Validate claim belongs to this contact + tenant\n  SELECT * INTO _claim FROM public.contact_claims\n   WHERE id = _claim_id\n     AND contact_id = _link.contact_id\n     AND tenant_org_id = _link.tenant_org_id\n   LIMIT 1;\n\n  IF _claim IS NULL THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Claim not found for this portal');\n  END IF;\n\n  UPDATE public.contact_claims\n     SET check_received_by_homeowner_at = CASE WHEN _received THEN now() ELSE NULL END,\n         check_received_notes = _notes,\n         updated_at = now()\n   WHERE id = _claim_id;\n\n  RETURN jsonb_build_object('ok', true);\nEND;\n$function$\n","identity_arguments":"_portal_token text, _claim_id uuid, _received boolean, _notes text"},{"name":"portal_get_roofing_project","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.portal_get_roofing_project(_portal_token text)\n RETURNS jsonb\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'extensions'\nAS $function$\ndeclare\n  v_contact_id uuid;\n  v_tenant_id uuid;\n  v_expires_at timestamptz;\n  v_job record;\n  v_ops record;\n  v_material record;\n  v_permit record;\n  v_closeout record;\n  v_token_hash text;\nbegin\n  select contact_id, tenant_org_id, expires_at\n    into v_contact_id, v_tenant_id, v_expires_at\n  from public.portal_links\n  where token = _portal_token\n    and is_active = true\n  limit 1;\n\n  if v_contact_id is null then\n    v_token_hash := encode(digest(_portal_token, 'sha256'), 'hex');\n    select contact_id, tenant_id, expires_at\n      into v_contact_id, v_tenant_id, v_expires_at\n    from public.customer_portal_access\n    where is_active = true\n      and (token_hash = v_token_hash or access_token = _portal_token)\n    limit 1;\n  end if;\n\n  if v_contact_id is null or v_tenant_id is null or (v_expires_at is not null and v_expires_at < now()) then\n    return null;\n  end if;\n\n  select id, status\n    into v_job\n  from public.jobs\n  where tenant_id = v_tenant_id\n    and contact_id = v_contact_id\n  order by updated_at desc nulls last, created_at desc\n  limit 1;\n\n  if not found then return null; end if;\n\n  select project_phase, install_date, materials_status, permit_status, closeout_status, warranty_status\n    into v_ops\n  from public.roofing_project_ops\n  where tenant_id = v_tenant_id\n    and job_id = v_job.id\n  limit 1;\n\n  if not found then return null; end if;\n\n  select status, delivery_date\n    into v_material\n  from public.roofing_material_orders\n  where tenant_id = v_tenant_id\n    and job_id = v_job.id\n  order by created_at desc\n  limit 1;\n\n  select status\n    into v_permit\n  from public.permits\n  where tenant_org_id = v_tenant_id\n    and contact_id = v_contact_id\n    and coalesce(is_roof_related, false) = true\n  order by updated_at desc nulls last, created_at desc\n  limit 1;\n\n  select final_photos_complete,\n         completion_certificate_complete,\n         warranty_registered,\n         homeowner_handoff_complete,\n         closed_at\n    into v_closeout\n  from public.roofing_closeout\n  where tenant_id = v_tenant_id\n    and job_id = v_job.id\n  limit 1;\n\n  return jsonb_build_object(\n    'phase', v_ops.project_phase,\n    'installDate', v_ops.install_date,\n    'materialStatus', coalesce(v_material.status, v_ops.materials_status),\n    'materialDeliveryDate', v_material.delivery_date,\n    'permitStatus', coalesce(v_permit.status, v_ops.permit_status),\n    'closeoutStatus', v_ops.closeout_status,\n    'warrantyStatus', v_ops.warranty_status,\n    'warrantyRegistered', coalesce(v_closeout.warranty_registered, false),\n    'finalPhotosComplete', coalesce(v_closeout.final_photos_complete, false),\n    'completionCertificateComplete', coalesce(v_closeout.completion_certificate_complete, false),\n    'homeownerHandoffComplete', coalesce(v_closeout.homeowner_handoff_complete, false),\n    'closedAt', v_closeout.closed_at\n  );\nend;\n$function$\n","identity_arguments":"_portal_token text"},{"name":"prevent_accepted_invitation_mutation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.prevent_accepted_invitation_mutation()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'pg_catalog', 'public'\nAS $function$\nbegin\n  if old.status = 'accepted' and (\n    new.status is distinct from old.status\n    or new.invitation_token is distinct from old.invitation_token\n    or new.email is distinct from old.email\n    or new.phone is distinct from old.phone\n    or new.tenant_id is distinct from old.tenant_id\n    or new.role is distinct from old.role\n  ) then\n    raise exception 'Accepted invitations are immutable';\n  end if;\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"prevent_dnc_audit_modification","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.prevent_dnc_audit_modification()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF auth.role() = 'service_role' THEN\n    RETURN NEW;\n  END IF;\n  RAISE EXCEPTION 'DNC audit entries are immutable for compliance. Modifications are not permitted.';\nEND;\n$function$\n","identity_arguments":""},{"name":"prevent_quarantine_modification","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.prevent_quarantine_modification()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF auth.role() = 'service_role' THEN RETURN NEW; END IF;\n  RAISE EXCEPTION 'DNC quarantine entries are immutable.';\nEND;\n$function$\n","identity_arguments":""},{"name":"progress_create_record","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.progress_create_record(_tenant_id uuid, _payload jsonb DEFAULT '{}'::jsonb)\n RETURNS business_opportunities\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  v_settings jsonb;\n  v_templates jsonb;\n  v_template jsonb;\n  v_stages jsonb;\n  v_template_id text;\n  v_requested_stage text;\n  v_stage text;\n  v_waiting_on text;\n  v_title text;\n  v_contact_id uuid;\n  v_id uuid := gen_random_uuid();\n  v_row public.business_opportunities%rowtype;\nbegin\n  if _tenant_id is null then raise exception 'progress_tenant_required'; end if;\n  if _payload is null or jsonb_typeof(_payload) <> 'object' then raise exception 'progress_payload_object_required'; end if;\n\n  perform public.business_engine_assert_access(_tenant_id);\n  select coalesce(settings, '{}'::jsonb) into v_settings from public.tenants where id = _tenant_id;\n  if not found then raise exception 'progress_tenant_not_found'; end if;\n  if coalesce(v_settings->>'workspace_type', '') <> 'progress_platform' then\n    raise exception 'progress_platform_not_enabled';\n  end if;\n\n  v_title := nullif(btrim(coalesce(_payload->>'title', '')), '');\n  if v_title is null then raise exception 'progress_title_required'; end if;\n\n  v_templates := case\n    when jsonb_typeof(v_settings->'progress_vertical_templates') = 'array' then v_settings->'progress_vertical_templates'\n    else '[]'::jsonb\n  end;\n  v_template_id := nullif(btrim(coalesce(_payload->>'template_id', '')), '');\n\n  if jsonb_array_length(v_templates) > 0 then\n    v_template_id := coalesce(v_template_id, nullif(v_settings->>'progress_default_template', ''), v_templates->0->>'id');\n    select item.value into v_template\n      from jsonb_array_elements(v_templates) as item(value)\n     where item.value->>'id' = v_template_id\n     limit 1;\n    if v_template is null then raise exception 'progress_template_invalid:%', coalesce(v_template_id, '<missing>'); end if;\n  else\n    v_stages := case\n      when jsonb_typeof(v_settings#>'{business_operating_blueprint,workflowStages}') = 'array'\n        then v_settings#>'{business_operating_blueprint,workflowStages}'\n      else jsonb_build_array('Received','In Review','In Progress','Waiting','Complete')\n    end;\n    v_template_id := coalesce(v_template_id, 'custom');\n    v_template := jsonb_build_object('id', v_template_id, 'label', 'Custom Progress', 'stages', v_stages);\n  end if;\n\n  v_stages := case when jsonb_typeof(v_template->'stages') = 'array' then v_template->'stages' else '[]'::jsonb end;\n  v_requested_stage := coalesce(nullif(btrim(coalesce(_payload->>'progress_stage', '')), ''), v_stages->>0);\n  select stage into v_stage\n    from jsonb_array_elements_text(v_stages) as stage\n   where lower(stage) = lower(v_requested_stage)\n   limit 1;\n  if v_stage is null then raise exception 'progress_stage_invalid:%', coalesce(v_requested_stage, '<missing>'); end if;\n\n  v_waiting_on := lower(coalesce(nullif(btrim(coalesce(_payload->>'waiting_on', '')), ''), 'none'));\n  if v_waiting_on not in ('none','customer','business') then raise exception 'progress_waiting_on_invalid:%', v_waiting_on; end if;\n\n  if _payload ? 'contact_id' and nullif(_payload->>'contact_id', '') is not null then\n    v_contact_id := (_payload->>'contact_id')::uuid;\n    if not exists (\n      select 1 from public.unified_contacts c\n       where c.id = v_contact_id and c.tenant_org_id = _tenant_id::text and c.deleted_at is null\n    ) then raise exception 'progress_contact_tenant_mismatch'; end if;\n  end if;\n\n  insert into public.business_opportunities (\n    id, tenant_id, contact_id, source_module, source_entity_type, dedupe_key,\n    title, summary, category, lifecycle_state, proposal_state, payment_state,\n    fulfillment_state, created_by, metadata\n  ) values (\n    v_id,\n    _tenant_id,\n    v_contact_id,\n    'progress-platform',\n    'progress_record',\n    'progress:' || v_id::text,\n    v_title,\n    nullif(btrim(coalesce(_payload->>'internal_summary', '')), ''),\n    coalesce(v_template->>'label', 'Progress'),\n    'captured',\n    'not_started',\n    'not_required',\n    'not_scheduled',\n    auth.uid(),\n    jsonb_strip_nulls(jsonb_build_object(\n      'template_id', v_template_id,\n      'template_label', v_template->>'label',\n      'progress_stage', v_stage,\n      'customer_name', nullif(btrim(coalesce(_payload->>'customer_name', '')), ''),\n      'next_step', nullif(btrim(coalesce(_payload->>'next_step', '')), ''),\n      'waiting_on', v_waiting_on,\n      'next_update_due_at', nullif(_payload->>'next_update_due_at', ''),\n      'target_date', nullif(_payload->>'target_date', ''),\n      'customer_visible_summary', nullif(btrim(coalesce(_payload->>'customer_visible_summary', '')), ''),\n      'last_progress_update_at', now()\n    ))\n  ) returning * into v_row;\n\n  insert into public.business_opportunity_events (\n    tenant_id, opportunity_id, dimension, from_state, to_state, reason_code, actor_user_id, metadata\n  ) values (\n    _tenant_id, v_row.id, 'progress', null, v_stage, 'progress_record_created', auth.uid(),\n    jsonb_build_object('template_id', v_template_id, 'source', 'progress-platform')\n  );\n\n  return v_row;\nend;\n$function$\n","identity_arguments":"_tenant_id uuid, _payload jsonb"},{"name":"progress_update_record","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.progress_update_record(_opportunity_id uuid, _patch jsonb)\n RETURNS business_opportunities\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'auth'\nAS $function$\ndeclare\n  v_row public.business_opportunities%rowtype;\n  v_final public.business_opportunities%rowtype;\n  v_settings jsonb;\n  v_templates jsonb;\n  v_template jsonb;\n  v_stages jsonb;\n  v_template_id text;\n  v_requested_stage text;\n  v_stage text;\n  v_old_stage text;\n  v_waiting_on text;\n  v_contact_id uuid;\n  v_metadata_patch jsonb := '{}'::jsonb;\n  v_allowed_keys constant text[] := array[\n    'contact_id','title','internal_summary','template_id','progress_stage','customer_name',\n    'next_step','waiting_on','next_update_due_at','target_date','customer_visible_summary'\n  ];\n  v_unknown_keys text[];\nbegin\n  if _patch is null or jsonb_typeof(_patch) <> 'object' then raise exception 'progress_patch_object_required'; end if;\n\n  select * into v_row from public.business_opportunities where id = _opportunity_id for update;\n  if not found then raise exception 'progress_record_not_found'; end if;\n  perform public.business_engine_assert_access(v_row.tenant_id);\n  if coalesce(v_row.source_entity_type, '') <> 'progress_record' then raise exception 'progress_record_type_mismatch'; end if;\n\n  select coalesce(settings, '{}'::jsonb) into v_settings from public.tenants where id = v_row.tenant_id;\n  if coalesce(v_settings->>'workspace_type', '') <> 'progress_platform' then raise exception 'progress_platform_not_enabled'; end if;\n\n  select array_agg(key) into v_unknown_keys\n    from jsonb_object_keys(_patch) as key\n   where not (key = any(v_allowed_keys));\n  if coalesce(cardinality(v_unknown_keys), 0) > 0 then\n    raise exception 'progress_patch_unknown_keys:%', array_to_string(v_unknown_keys, ',');\n  end if;\n  if _patch ? 'title' and nullif(btrim(coalesce(_patch->>'title', '')), '') is null then raise exception 'progress_title_required'; end if;\n\n  v_templates := case\n    when jsonb_typeof(v_settings->'progress_vertical_templates') = 'array' then v_settings->'progress_vertical_templates'\n    else '[]'::jsonb\n  end;\n  v_template_id := coalesce(nullif(btrim(coalesce(_patch->>'template_id', '')), ''), v_row.metadata->>'template_id', nullif(v_settings->>'progress_default_template', ''));\n\n  if jsonb_array_length(v_templates) > 0 then\n    v_template_id := coalesce(v_template_id, v_templates->0->>'id');\n    select item.value into v_template\n      from jsonb_array_elements(v_templates) as item(value)\n     where item.value->>'id' = v_template_id\n     limit 1;\n    if v_template is null then raise exception 'progress_template_invalid:%', coalesce(v_template_id, '<missing>'); end if;\n  else\n    v_stages := case\n      when jsonb_typeof(v_settings#>'{business_operating_blueprint,workflowStages}') = 'array'\n        then v_settings#>'{business_operating_blueprint,workflowStages}'\n      else jsonb_build_array('Received','In Review','In Progress','Waiting','Complete')\n    end;\n    v_template_id := coalesce(v_template_id, 'custom');\n    v_template := jsonb_build_object('id', v_template_id, 'label', 'Custom Progress', 'stages', v_stages);\n  end if;\n\n  v_stages := case when jsonb_typeof(v_template->'stages') = 'array' then v_template->'stages' else '[]'::jsonb end;\n  v_old_stage := nullif(v_row.metadata->>'progress_stage', '');\n  v_requested_stage := coalesce(nullif(btrim(coalesce(_patch->>'progress_stage', '')), ''), v_old_stage, v_stages->>0);\n  select stage into v_stage\n    from jsonb_array_elements_text(v_stages) as stage\n   where lower(stage) = lower(v_requested_stage)\n   limit 1;\n  if v_stage is null then raise exception 'progress_stage_invalid:%', coalesce(v_requested_stage, '<missing>'); end if;\n\n  v_waiting_on := lower(coalesce(\n    case when _patch ? 'waiting_on' then nullif(btrim(coalesce(_patch->>'waiting_on', '')), '') else null end,\n    v_row.metadata->>'waiting_on',\n    'none'\n  ));\n  if v_waiting_on not in ('none','customer','business') then raise exception 'progress_waiting_on_invalid:%', v_waiting_on; end if;\n\n  if _patch ? 'contact_id' then\n    if nullif(_patch->>'contact_id', '') is null then\n      v_contact_id := null;\n    else\n      v_contact_id := (_patch->>'contact_id')::uuid;\n      if not exists (\n        select 1 from public.unified_contacts c\n         where c.id = v_contact_id and c.tenant_org_id = v_row.tenant_id::text and c.deleted_at is null\n      ) then raise exception 'progress_contact_tenant_mismatch'; end if;\n    end if;\n  else\n    v_contact_id := v_row.contact_id;\n  end if;\n\n  if _patch ? 'template_id' then v_metadata_patch := v_metadata_patch || jsonb_build_object('template_id', v_template_id, 'template_label', v_template->>'label'); end if;\n  if _patch ? 'progress_stage' or v_old_stage is null then v_metadata_patch := v_metadata_patch || jsonb_build_object('progress_stage', v_stage); end if;\n  if _patch ? 'customer_name' then v_metadata_patch := v_metadata_patch || jsonb_build_object('customer_name', nullif(btrim(coalesce(_patch->>'customer_name', '')), '')); end if;\n  if _patch ? 'next_step' then v_metadata_patch := v_metadata_patch || jsonb_build_object('next_step', nullif(btrim(coalesce(_patch->>'next_step', '')), '')); end if;\n  if _patch ? 'waiting_on' then v_metadata_patch := v_metadata_patch || jsonb_build_object('waiting_on', v_waiting_on); end if;\n  if _patch ? 'next_update_due_at' then v_metadata_patch := v_metadata_patch || jsonb_build_object('next_update_due_at', nullif(_patch->>'next_update_due_at', '')); end if;\n  if _patch ? 'target_date' then v_metadata_patch := v_metadata_patch || jsonb_build_object('target_date', nullif(_patch->>'target_date', '')); end if;\n  if _patch ? 'customer_visible_summary' then v_metadata_patch := v_metadata_patch || jsonb_build_object('customer_visible_summary', nullif(btrim(coalesce(_patch->>'customer_visible_summary', '')), '')); end if;\n  v_metadata_patch := v_metadata_patch || jsonb_build_object('last_progress_update_at', now());\n\n  update public.business_opportunities\n     set contact_id = v_contact_id,\n         title = case when _patch ? 'title' then btrim(_patch->>'title') else title end,\n         summary = case when _patch ? 'internal_summary' then nullif(btrim(coalesce(_patch->>'internal_summary', '')), '') else summary end,\n         category = case when _patch ? 'template_id' then coalesce(v_template->>'label', category) else category end,\n         metadata = metadata || v_metadata_patch,\n         updated_at = now()\n   where id = v_row.id\n   returning * into v_final;\n\n  insert into public.business_opportunity_events (\n    tenant_id, opportunity_id, dimension, from_state, to_state, reason_code, actor_user_id, metadata\n  ) values (\n    v_row.tenant_id,\n    v_row.id,\n    'progress',\n    v_old_stage,\n    v_stage,\n    case when v_old_stage is distinct from v_stage then 'progress_stage_changed' else 'progress_record_updated' end,\n    auth.uid(),\n    _patch\n  );\n\n  return v_final;\nend;\n$function$\n","identity_arguments":"_opportunity_id uuid, _patch jsonb"},{"name":"propagate_dnc_to_leads","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.propagate_dnc_to_leads()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_normalized text;\nBEGIN\n  v_normalized := NEW.phone_normalized;\n  IF v_normalized IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  UPDATE public.lead_deck\n  SET is_dnc = true,\n      dnc_reason = COALESCE(NEW.reason, 'Matched DNC list'),\n      dnc_checked_at = now(),\n      status = 'DNC',\n      updated_at = now()\n  WHERE public.normalize_phone_for_dnc(phone) = v_normalized\n    AND is_dnc = false;\n\n  UPDATE public.unified_contacts\n  SET is_dnc = true,\n      dnc_reason = COALESCE(NEW.reason, 'Matched DNC list'),\n      dnc_checked_at = now(),\n      status = 'DNC',\n      updated_at = now()\n  WHERE public.normalize_phone_for_dnc(phone) = v_normalized\n    AND is_dnc = false;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"propagate_federal_dnc_to_contacts","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.propagate_federal_dnc_to_contacts()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_last10 text;\nBEGIN\n  v_last10 := right(regexp_replace(NEW.phone, '\\D', '', 'g'), 10);\n  IF v_last10 IS NULL OR length(v_last10) <> 10 THEN\n    RETURN NEW;\n  END IF;\n  UPDATE public.unified_contacts\n  SET is_dnc = true,\n      updated_at = now()\n  WHERE is_dnc IS DISTINCT FROM true\n    AND right(regexp_replace(coalesce(phone, ''), '\\D', '', 'g'), 10) = v_last10;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"propagate_florida_dnc_to_contacts","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.propagate_florida_dnc_to_contacts()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_last10 text;\nBEGIN\n  v_last10 := right(regexp_replace(NEW.phone_normalized, '\\D', '', 'g'), 10);\n  IF v_last10 IS NULL OR length(v_last10) <> 10 THEN\n    RETURN NEW;\n  END IF;\n  UPDATE public.unified_contacts\n  SET is_dnc = true,\n      updated_at = now()\n  WHERE is_dnc IS DISTINCT FROM true\n    AND right(regexp_replace(coalesce(phone, ''), '\\D', '', 'g'), 10) = v_last10;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"protect_forward_phone","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.protect_forward_phone()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _normalized text;\n  _conflict   record;\nBEGIN\n  IF NEW.forward_to_phone IS NULL OR NEW.forward_to_phone = '' THEN\n    RETURN NEW;\n  END IF;\n\n  _normalized := regexp_replace(NEW.forward_to_phone, '\\D', '', 'g');\n  IF length(_normalized) < 10 THEN\n    RETURN NEW;\n  END IF;\n\n  SELECT id, phone_number, friendly_name INTO _conflict\n  FROM public.tenant_phone_numbers\n  WHERE regexp_replace(phone_number, '\\D', '', 'g') = _normalized\n  LIMIT 1;\n\n  IF FOUND THEN\n    RAISE EXCEPTION 'forward_phone_collision: % is a tenant-owned Twilio number (%) and cannot be the bridge target',\n      NEW.forward_to_phone, _conflict.friendly_name\n      USING ERRCODE = 'check_violation',\n            HINT = 'Forward target must be the rep''s real cell phone, not a Twilio DID.';\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"protect_profile_phone","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.protect_profile_phone()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _normalized text;\n  _conflict   record;\nBEGIN\n  IF NEW.phone IS NULL OR NEW.phone = '' THEN\n    RETURN NEW;\n  END IF;\n\n  _normalized := regexp_replace(NEW.phone, '\\D', '', 'g');\n  IF length(_normalized) < 10 THEN\n    RETURN NEW; -- let app-level validation handle bad formats\n  END IF;\n\n  SELECT id, phone_number, friendly_name, tenant_org_id INTO _conflict\n  FROM public.tenant_phone_numbers\n  WHERE regexp_replace(phone_number, '\\D', '', 'g') = _normalized\n  LIMIT 1;\n\n  IF FOUND THEN\n    RAISE EXCEPTION 'phone_collision: % is a tenant-owned Twilio number (%) and cannot be saved as a personal cell',\n      NEW.phone, _conflict.friendly_name\n      USING ERRCODE = 'check_violation',\n            HINT = 'Use the user''s real personal cell. Tenant Twilio numbers are managed under Communications Hub.';\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"provision_my_onboarding_session","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.provision_my_onboarding_session(p_session_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_uid uuid := auth.uid();\n  s public.onboarding_sessions%rowtype;\n  v_readiness jsonb;\n  v_blueprint jsonb;\n  v_tenant_id uuid;\n  v_slug text;\n  v_track text;\n  v_templates jsonb;\n  v_foundation jsonb;\n  v_pending int := 0;\n  v_owner_review int := 0;\n  v_operator_review int := 0;\n  v_failed int := 0;\nbegin\n  if v_uid is null then raise exception 'Authentication required' using errcode='42501'; end if;\n  select * into s from public.onboarding_sessions where id=p_session_id and (owner_user_id=v_uid or public.is_system_admin(v_uid));\n  if not found then raise exception 'Onboarding session not found' using errcode='42501'; end if;\n\n  v_blueprint:=public.derive_onboarding_blueprint(p_session_id);\n  v_readiness:=public.refresh_onboarding_readiness(p_session_id);\n  if jsonb_array_length(coalesce(v_readiness->'missing','[]'::jsonb))>0 then\n    return public.get_my_onboarding_context(p_session_id)||jsonb_build_object('provisioned',false,'reason','needs_input');\n  end if;\n\n  select * into s from public.onboarding_sessions where id=p_session_id;\n  v_tenant_id:=s.tenant_id;\n  v_track:=public.academy_track_for_type(s.canonical_tenant_type);\n\n  if v_tenant_id is null then\n    v_tenant_id:=gen_random_uuid();\n    v_slug:=coalesce(nullif(s.company_slug,''),trim(both '-' from regexp_replace(lower(s.company_name),'[^a-z0-9]+','-','g'))||'-'||substr(replace(s.id::text,'-',''),1,6));\n    insert into public.tenants(id,name,tenant_type,owner_id,status,settings,company_slug,company_state,company_email,company_website,is_active)\n    values(v_tenant_id,s.company_name,s.canonical_tenant_type,v_uid,'active',jsonb_build_object('onboarding_session_id',s.id,'onboarding_blueprint',v_blueprint,'service_lines',s.service_lines,'goals',s.goals,'requested_capabilities',s.requested_capabilities,'service_area',s.service_area),v_slug,case when cardinality(s.operating_states)>0 then s.operating_states[1] else null end,s.email,nullif(s.intake_answers->>'website',''),true);\n    update public.onboarding_sessions set tenant_id=v_tenant_id,company_slug=v_slug,status='provisioning',updated_at=now() where id=p_session_id;\n  else\n    update public.onboarding_sessions set status='provisioning',updated_at=now() where id=p_session_id;\n  end if;\n\n  v_templates:=public.clone_onboarding_templates_internal(v_tenant_id,s.canonical_tenant_type,v_track);\n  v_foundation:=public.ensure_tenant_provisioning_foundation(v_tenant_id,v_uid,'Tenant Owner');\n\n  insert into public.tenant_readiness_checks(tenant_id,check_key,status,detail) values\n    (v_tenant_id,'experience','ready',jsonb_build_object('templates',v_templates,'editor','PlatformExperienceEditor')),\n    (v_tenant_id,'service_area','ready',jsonb_build_object('states',s.operating_states,'service_area',s.service_area)),\n    (v_tenant_id,'capabilities','pending',jsonb_build_object('requested',s.requested_capabilities,'recommended',v_blueprint->'recommended_capabilities'))\n  on conflict (tenant_id,check_key) do update set status=excluded.status,detail=excluded.detail,updated_at=now();\n\n  select count(*) into v_pending from public.onboarding_research_tasks where session_id=p_session_id and status in ('pending','running');\n  select count(*) into v_owner_review from public.onboarding_research_tasks where session_id=p_session_id and status in ('needs_review','not_found') and coalesce((result->>'owner_input_required')::boolean,false)=true;\n  select count(*) into v_operator_review from public.onboarding_research_tasks where session_id=p_session_id and status in ('needs_review','not_found') and coalesce((result->>'owner_input_required')::boolean,false)=false;\n  select count(*) into v_failed from public.onboarding_research_tasks where session_id=p_session_id and status='failed';\n\n  insert into public.tenant_readiness_checks(tenant_id,check_key,status,detail)\n  values(v_tenant_id,'licensing',case when v_owner_review>0 then 'needs_input' when v_pending>0 or v_operator_review>0 or v_failed>0 then 'pending' else 'ready' end,jsonb_build_object('pending',v_pending,'owner_input_required',v_owner_review,'operator_review',v_operator_review,'failed',v_failed))\n  on conflict (tenant_id,check_key) do update set status=excluded.status,detail=excluded.detail,updated_at=now();\n\n  if not coalesce((v_foundation->>'ok')::boolean,false) then\n    update public.onboarding_sessions set status='failed',last_error='Academy onboarding could not be provisioned',updated_at=now() where id=p_session_id;\n    return public.get_my_onboarding_context(p_session_id)||jsonb_build_object('provisioned',false,'foundation',v_foundation,'templates',v_templates);\n  end if;\n\n  update public.onboarding_sessions set status=case when v_owner_review>0 then 'needs_input' when v_pending>0 then 'validating' else 'ready' end,last_error=null,updated_at=now() where id=p_session_id;\n  return public.get_my_onboarding_context(p_session_id)||jsonb_build_object('provisioned',true,'tenant_id',v_tenant_id,'foundation',v_foundation,'templates',v_templates);\nexception when others then\n  update public.onboarding_sessions set status='failed',last_error=sqlerrm,updated_at=now() where id=p_session_id;\n  raise;\nend;\n$function$\n","identity_arguments":"p_session_id uuid"},{"name":"publish_live_edit_override","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.publish_live_edit_override(_tenant_id uuid, _route_path text, _operations jsonb)\n RETURNS TABLE(override_id uuid, revision_id uuid)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  _user_id uuid := public.request_user_id();\n  _override_id uuid;\n  _revision_id uuid;\n  _parent_revision_id uuid;\n  _existing_operations jsonb := '[]'::jsonb;\n  _non_live_operations jsonb := '[]'::jsonb;\nbegin\n  if _user_id is null then raise exception 'Authentication required'; end if;\n  if not public.can_manage_page_override(_user_id, _tenant_id::text) then raise exception 'Tenant edit access denied'; end if;\n  if _route_path is null or length(_route_path) < 1 or length(_route_path) > 512 then raise exception 'Invalid route'; end if;\n  if not public.live_edit_operations_safe(_operations) then raise exception 'Unsafe Live Edit operations'; end if;\n\n  select id, operations into _override_id, _existing_operations\n  from public.godmode_page_overrides\n  where tenant_scope = _tenant_id::text\n    and route_path = _route_path\n    and status = 'published'\n    and (title = 'Live page edits' or metadata->>'source' in ('live-edit-v1','live-edit-v2'))\n  order by published_at desc nulls last, updated_at desc\n  limit 1\n  for update;\n\n  if _override_id is not null then\n    select coalesce(jsonb_agg(value), '[]'::jsonb) into _non_live_operations\n    from jsonb_array_elements(coalesce(_existing_operations, '[]'::jsonb))\n    where coalesce(value#>>'{audit,source}', '') <> 'live-edit';\n\n    update public.godmode_page_overrides\n    set operations = _non_live_operations || _operations,\n        status = 'published',\n        title = 'Live page edits',\n        metadata = coalesce(metadata, '{}'::jsonb) || jsonb_build_object('source','live-edit-v2'),\n        version = coalesce(version, 0) + 1,\n        updated_by = _user_id,\n        published_by = _user_id,\n        updated_at = now(),\n        published_at = now()\n    where id = _override_id;\n  else\n    insert into public.godmode_page_overrides (\n      route_path, tenant_scope, device_scope, status, title, operations, metadata,\n      created_by, updated_by, published_by, created_at, updated_at, published_at\n    ) values (\n      _route_path, _tenant_id::text, 'all', 'published', 'Live page edits', _operations,\n      jsonb_build_object('source','live-edit-v2'), _user_id, _user_id, _user_id, now(), now(), now()\n    ) returning id into _override_id;\n  end if;\n\n  select id into _parent_revision_id\n  from public.live_edit_revisions\n  where tenant_id = _tenant_id and route_path = _route_path\n  order by created_at desc\n  limit 1;\n\n  insert into public.live_edit_revisions (\n    tenant_id, route_path, override_id, parent_revision_id, operations, created_by\n  ) values (\n    _tenant_id, _route_path, _override_id, _parent_revision_id, _operations, _user_id\n  ) returning id into _revision_id;\n\n  delete from public.godmode_page_overrides\n  where tenant_scope = _tenant_id::text\n    and route_path = _route_path\n    and status = 'draft'\n    and title = 'Live page draft'\n    and metadata->>'source' = 'live-edit-v2';\n\n  return query select _override_id, _revision_id;\nend;\n$function$\n","identity_arguments":"_tenant_id uuid, _route_path text, _operations jsonb"},{"name":"purge_call_lifecycle_events","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.purge_call_lifecycle_events()\n RETURNS void\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  DELETE FROM public.call_lifecycle_events WHERE created_at < now() - interval '7 days';\n$function$\n","identity_arguments":""},{"name":"queue_onboarding_license_research","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.queue_onboarding_license_research(p_session_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  s public.onboarding_sessions%rowtype; v_state text; v_business_type text; v_source record; v_owner_name text; v_license_number text; v_mode text; v_query jsonb; v_result jsonb; v_status text; v_error text; v_token uuid; v_queued int := 0; v_owner_input int := 0; v_operator_review int := 0;\nBEGIN\n  SELECT * INTO s FROM public.onboarding_sessions WHERE id=p_session_id;\n  IF NOT FOUND THEN RAISE EXCEPTION 'Onboarding session not found'; END IF;\n  IF coalesce(auth.role(),'') <> 'service_role' THEN IF auth.uid() IS NULL OR (s.owner_user_id IS DISTINCT FROM auth.uid() AND NOT public.is_system_admin(auth.uid())) THEN RAISE EXCEPTION 'Not authorized for this onboarding session' USING ERRCODE='42501'; END IF; END IF;\n  IF cardinality(s.operating_states)=0 THEN RETURN public.refresh_onboarding_readiness(p_session_id); END IF;\n  v_business_type := public.canonical_tenant_type(s.requested_business_type);\n  IF v_business_type IS NULL THEN RETURN public.refresh_onboarding_readiness(p_session_id); END IF;\n  SELECT p.name,p.license_number INTO v_owner_name,v_license_number FROM public.profiles p WHERE p.id=s.owner_user_id;\n  v_owner_name := coalesce(nullif(s.intake_answers->>'owner_name',''),nullif(v_owner_name,''));\n  v_license_number := coalesce(nullif(s.intake_answers->>'license_number',''),nullif(v_license_number,''));\n  FOREACH v_state IN ARRAY s.operating_states LOOP\n    SELECT * INTO v_source FROM public.onboarding_license_sources ls WHERE upper(ls.jurisdiction)=upper(v_state) AND ls.business_type=v_business_type AND ls.is_active=true AND ls.is_official=true ORDER BY CASE WHEN ls.metadata->>'automation_mode'='automated' THEN 0 ELSE 1 END, ls.created_at ASC LIMIT 1;\n    v_query := jsonb_build_object('company_name',s.company_name,'business_type',v_business_type,'jurisdiction',upper(v_state),'owner_name',v_owner_name,'license_number',v_license_number);\n    IF FOUND THEN\n      v_mode := coalesce(v_source.metadata->>'automation_mode','interactive_required');\n      IF v_mode='automated' AND (coalesce(v_owner_name,'')<>'' OR coalesce(v_license_number,'')<>'') THEN v_status:='pending'; v_error:=null; v_token:=gen_random_uuid(); v_result:='{}'::jsonb; v_queued:=v_queued+1;\n      ELSIF v_mode='automated' THEN v_status:='needs_review'; v_error:='Owner name or license number is needed to complete the official license lookup'; v_token:=null; v_result:=jsonb_build_object('owner_input_required',true,'missing',jsonb_build_array('owner_name')); v_owner_input:=v_owner_input+1;\n      ELSE v_status:='needs_review'; v_error:=coalesce(v_source.metadata->>'reason','This official registry requires interactive verification'); v_token:=null; v_result:=jsonb_build_object('owner_input_required',false,'review_type','knocklaunch_operator','reason',v_error); v_operator_review:=v_operator_review+1; END IF;\n      INSERT INTO public.onboarding_research_tasks(session_id,research_type,jurisdiction,provider_key,query,result,status,source_url,last_error,dispatch_token,dispatched_at)\n      VALUES(p_session_id,'license_verification',upper(v_state),v_source.provider_key,v_query,v_result,v_status,v_source.source_url,v_error,v_token,CASE WHEN v_token IS NOT NULL THEN now() ELSE null END)\n      ON CONFLICT (session_id,research_type,jurisdiction) DO UPDATE SET provider_key=excluded.provider_key,query=excluded.query,source_url=excluded.source_url,result=CASE WHEN public.onboarding_research_tasks.status='verified' THEN public.onboarding_research_tasks.result ELSE excluded.result END,status=CASE WHEN public.onboarding_research_tasks.status='verified' THEN 'verified' ELSE excluded.status END,last_error=CASE WHEN public.onboarding_research_tasks.status='verified' THEN null ELSE excluded.last_error END,dispatch_token=CASE WHEN public.onboarding_research_tasks.status='verified' THEN null ELSE excluded.dispatch_token END,dispatched_at=CASE WHEN public.onboarding_research_tasks.status='verified' THEN public.onboarding_research_tasks.dispatched_at ELSE excluded.dispatched_at END,updated_at=now();\n    ELSE\n      v_result:=jsonb_build_object('owner_input_required',false,'review_type','knocklaunch_operator','reason','No configured authoritative licensing source for this jurisdiction/business type');\n      INSERT INTO public.onboarding_research_tasks(session_id,research_type,jurisdiction,provider_key,query,result,status,last_error,dispatch_token)\n      VALUES(p_session_id,'license_verification',upper(v_state),null,v_query,v_result,'needs_review','No configured authoritative licensing source for this jurisdiction/business type',null)\n      ON CONFLICT (session_id,research_type,jurisdiction) DO UPDATE SET provider_key=null,query=excluded.query,source_url=null,result=CASE WHEN public.onboarding_research_tasks.status='verified' THEN public.onboarding_research_tasks.result ELSE excluded.result END,status=CASE WHEN public.onboarding_research_tasks.status='verified' THEN 'verified' ELSE 'needs_review' END,last_error=CASE WHEN public.onboarding_research_tasks.status='verified' THEN null ELSE excluded.last_error END,dispatch_token=null,updated_at=now();\n      v_operator_review:=v_operator_review+1;\n    END IF;\n  END LOOP;\n  PERFORM public.refresh_onboarding_readiness(p_session_id);\n  RETURN jsonb_build_object('ok',true,'session_id',p_session_id,'queued',v_queued,'owner_input_required',v_owner_input,'operator_review',v_operator_review,'business_type',v_business_type);\nEND;\n$function$\n","identity_arguments":"p_session_id uuid"},{"name":"read_email_batch","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.read_email_batch(queue_name text, batch_size integer, vt integer)\n RETURNS TABLE(msg_id bigint, read_ct integer, message jsonb)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_catalog'\nAS $function$\nBEGIN\n  RETURN QUERY SELECT r.msg_id, r.read_ct, r.message FROM pgmq.read(queue_name, vt, batch_size) r;\nEXCEPTION WHEN undefined_table THEN\n  PERFORM pgmq.create(queue_name);\n  RETURN;\nEND;\n$function$\n","identity_arguments":"queue_name text, batch_size integer, vt integer"},{"name":"realtor_campaign_property_tenant_guard","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.realtor_campaign_property_tenant_guard()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  c_tenant uuid;\n  p_tenant uuid;\nBEGIN\n  SELECT tenant_id INTO c_tenant FROM public.realtor_campaigns WHERE id = NEW.campaign_id;\n  SELECT tenant_id INTO p_tenant FROM public.realtor_properties WHERE id = NEW.property_id;\n  IF c_tenant IS NULL OR p_tenant IS NULL THEN\n    RAISE EXCEPTION 'Campaign or property not found';\n  END IF;\n  IF c_tenant <> NEW.tenant_id OR p_tenant <> NEW.tenant_id THEN\n    RAISE EXCEPTION 'Cross-tenant campaign/property link rejected';\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"recalc_academy_enrollment_progress","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.recalc_academy_enrollment_progress(_user_id uuid, _course_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_total_lessons int;\n  v_completed_lessons int;\n  v_pct int;\n  v_status text;\nBEGIN\n  -- Total lessons in the course (via units)\n  SELECT COUNT(*)::int INTO v_total_lessons\n  FROM public.academy_lessons l\n  JOIN public.academy_units u ON u.id = l.unit_id\n  WHERE u.course_id = _course_id;\n\n  -- Completed lessons by this user for this course\n  SELECT COUNT(*)::int INTO v_completed_lessons\n  FROM public.academy_trainee_progress tp\n  WHERE tp.user_id = _user_id\n    AND tp.course_id = _course_id\n    AND (tp.status = 'completed' OR tp.completed_at IS NOT NULL);\n\n  IF v_total_lessons > 0 THEN\n    v_pct := LEAST(100, ROUND((v_completed_lessons::numeric / v_total_lessons::numeric) * 100)::int);\n  ELSE\n    v_pct := 0;\n  END IF;\n\n  IF v_pct >= 100 THEN\n    v_status := 'completed';\n  ELSIF v_pct > 0 THEN\n    v_status := 'active';\n  ELSE\n    v_status := 'active';\n  END IF;\n\n  -- Upsert the enrollment row (auto-enroll if missing so progress is never lost)\n  INSERT INTO public.academy_enrollments (user_id, course_id, status, progress_percent, completed_at, created_at, updated_at)\n  VALUES (\n    _user_id,\n    _course_id,\n    v_status,\n    v_pct,\n    CASE WHEN v_pct >= 100 THEN now() ELSE NULL END,\n    now(),\n    now()\n  )\n  ON CONFLICT (user_id, course_id) DO UPDATE\n  SET progress_percent = EXCLUDED.progress_percent,\n      status = EXCLUDED.status,\n      completed_at = CASE WHEN EXCLUDED.progress_percent >= 100\n                          THEN COALESCE(public.academy_enrollments.completed_at, now())\n                          ELSE NULL END,\n      updated_at = now();\nEND;\n$function$\n","identity_arguments":"_user_id uuid, _course_id uuid"},{"name":"reconcile_configured_lead_source_routing_on_membership","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.reconcile_configured_lead_source_routing_on_membership()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare v_email text;\nbegin\n  if new.status <> 'active' then return new; end if;\n  select p.email into v_email from public.profiles p where p.id=new.user_id;\n  if nullif(btrim(coalesce(v_email,'')),'') is null then return new; end if;\n  update public.unified_contacts c set source=c.source,updated_at=now() from public.tenants t where t.id=new.tenant_id and c.tenant_org_id=new.tenant_id::text and lower(coalesce(t.settings->'lead_source_routing'->c.source->>'assignee_email',''))=lower(v_email);\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"reconcile_default_role_insert","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.reconcile_default_role_insert()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\ndeclare v_existing public.user_roles%rowtype;\nbegin\n  if new.tenant_id is null then return new; end if;\n  select * into v_existing from public.user_roles where user_id=new.user_id and tenant_id=new.tenant_id limit 1;\n  if not found then return new; end if;\n  if v_existing.role = new.role then\n    if new.assigned_by is not null and v_existing.assigned_by is null then\n      update public.user_roles set assigned_by=new.assigned_by, assigned_at=coalesce(new.assigned_at,now()) where id=v_existing.id;\n    end if;\n    return null;\n  end if;\n  if v_existing.role in ('Rep'::app_role,'Tenant Owner'::app_role) and new.assigned_by is not null then\n    update public.user_roles set role=new.role, assigned_by=new.assigned_by, assigned_at=coalesce(new.assigned_at,now()) where id=v_existing.id;\n    return null;\n  end if;\n  raise exception 'Conflicting explicit tenant role for user % tenant %: existing %, requested %',new.user_id,new.tenant_id,v_existing.role,new.role;\nend;\n$function$\n","identity_arguments":""},{"name":"record_content_version","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.record_content_version(_course_id uuid, _lesson_id uuid, _content_hash text, _reason text)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_id uuid;\n  v_ver int;\nBEGIN\n  IF NOT (is_system_admin(auth.uid())) THEN\n    RAISE EXCEPTION 'Only GodMode may record content versions';\n  END IF;\n  IF _course_id IS NOT NULL THEN\n    UPDATE public.academy_courses SET version = version + 1, content_hash = COALESCE(_content_hash, content_hash), updated_at = now()\n    WHERE id = _course_id RETURNING version INTO v_ver;\n  END IF;\n  IF _lesson_id IS NOT NULL THEN\n    UPDATE public.academy_lessons SET content_hash = COALESCE(_content_hash, content_hash), updated_at = now()\n    WHERE id = _lesson_id;\n  END IF;\n  INSERT INTO public.academy_content_versions(course_id, lesson_id, version, content_hash, reason, changed_by)\n  VALUES (_course_id, _lesson_id, COALESCE(v_ver, 1), _content_hash, _reason, auth.uid())\n  RETURNING id INTO v_id;\n  RETURN v_id;\nEND;\n$function$\n","identity_arguments":"_course_id uuid, _lesson_id uuid, _content_hash text, _reason text"},{"name":"record_mobile_vendor_loyalty_purchase","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.record_mobile_vendor_loyalty_purchase(_tenant_org_id uuid, _member_id uuid, _purchase_ref text, _payment_method text DEFAULT 'cash'::text, _amount_cents integer DEFAULT NULL::integer, _source text DEFAULT 'owner_action'::text, _source_transaction_id text DEFAULT NULL::text, _confirmed_by_user_id uuid DEFAULT NULL::uuid, _referral_points integer DEFAULT 100)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_purchase public.mobile_vendor_loyalty_purchases%rowtype;\n  v_visit jsonb;\n  v_ref text := nullif(btrim(coalesce(_purchase_ref, '')), '');\n  v_method text := lower(btrim(coalesce(_payment_method, 'cash')));\n  v_source text := nullif(btrim(coalesce(_source, 'owner_action')), '');\n  v_source_transaction_id text := nullif(btrim(coalesce(_source_transaction_id, '')), '');\nbegin\n  if v_ref is null then raise exception 'Purchase reference is required'; end if;\n  if v_method not in ('cash', 'square', 'other') then raise exception 'Unsupported payment method'; end if;\n  if _amount_cents is not null and _amount_cents < 0 then raise exception 'Purchase amount cannot be negative'; end if;\n  if v_source is null then v_source := 'owner_action'; end if;\n\n  select * into v_purchase\n  from public.mobile_vendor_loyalty_purchases\n  where tenant_org_id = _tenant_org_id and purchase_ref = v_ref\n  for update;\n\n  if found then\n    return jsonb_build_object(\n      'ok', true,\n      'already_recorded', true,\n      'purchase_id', v_purchase.id,\n      'purchase_ref', v_purchase.purchase_ref,\n      'payment_method', v_purchase.payment_method,\n      'occurred_at', v_purchase.occurred_at,\n      'reason', 'idempotent_replay'\n    );\n  end if;\n\n  insert into public.mobile_vendor_loyalty_purchases (\n    tenant_org_id, member_id, purchase_ref, payment_method, amount_cents, currency,\n    source, source_transaction_id, confirmed_by_user_id, status, metadata\n  ) values (\n    _tenant_org_id, _member_id, v_ref, v_method, _amount_cents, 'USD',\n    v_source, v_source_transaction_id, _confirmed_by_user_id, 'confirmed',\n    jsonb_build_object('loyalty_qualifying', true)\n  )\n  returning * into v_purchase;\n\n  v_visit := public.record_mobile_vendor_loyalty_visit(\n    _tenant_org_id,\n    _member_id,\n    v_ref,\n    _referral_points\n  );\n\n  update public.mobile_vendor_loyalty_purchases\n  set metadata = coalesce(metadata, '{}'::jsonb) || jsonb_build_object('loyalty_result', v_visit),\n      updated_at = now()\n  where id = v_purchase.id;\n\n  return jsonb_build_object(\n    'ok', true,\n    'already_recorded', false,\n    'purchase_id', v_purchase.id,\n    'purchase_ref', v_purchase.purchase_ref,\n    'payment_method', v_purchase.payment_method,\n    'occurred_at', v_purchase.occurred_at,\n    'visit', v_visit,\n    'referral_event', v_visit->>'referral_event'\n  );\nexception\n  when unique_violation then\n    select * into v_purchase\n    from public.mobile_vendor_loyalty_purchases\n    where tenant_org_id = _tenant_org_id\n      and (purchase_ref = v_ref or (v_source_transaction_id is not null and payment_method = v_method and source_transaction_id = v_source_transaction_id))\n    order by created_at asc\n    limit 1;\n    if found then\n      return jsonb_build_object(\n        'ok', true,\n        'already_recorded', true,\n        'purchase_id', v_purchase.id,\n        'purchase_ref', v_purchase.purchase_ref,\n        'payment_method', v_purchase.payment_method,\n        'occurred_at', v_purchase.occurred_at,\n        'reason', 'idempotent_replay'\n      );\n    end if;\n    raise;\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _member_id uuid, _purchase_ref text, _payment_method text, _amount_cents integer, _source text, _source_transaction_id text, _confirmed_by_user_id uuid, _referral_points integer"},{"name":"record_mobile_vendor_loyalty_visit","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.record_mobile_vendor_loyalty_visit(_tenant_org_id uuid, _member_id uuid, _visit_ref text DEFAULT NULL::text, _referral_points integer DEFAULT 100)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_member public.mobile_vendor_loyalty_members%rowtype;\n  v_referrer public.mobile_vendor_loyalty_members%rowtype;\n  v_referral public.mobile_vendor_loyalty_referrals%rowtype;\n  v_now timestamptz := now();\n  v_next_stamps integer;\n  v_points integer;\n  v_event text := null;\n  v_first_purchase_recorded boolean := false;\n  v_visit_ref text := nullif(btrim(coalesce(_visit_ref, '')), '');\nbegin\n  select * into v_member\n  from public.mobile_vendor_loyalty_members\n  where tenant_org_id = _tenant_org_id and id = _member_id\n  for update;\n  if not found or v_member.status <> 'active' then raise exception 'Active loyalty member not found'; end if;\n\n  if v_visit_ref is not null and exists (\n    select 1 from public.mobile_vendor_loyalty_activity\n    where tenant_org_id = _tenant_org_id and member_id = v_member.id\n      and activity_type = 'visit' and source = 'owner_action' and source_ref = v_visit_ref\n  ) then\n    return jsonb_build_object('ok', true, 'already_recorded', true, 'member_id', v_member.id, 'stamp_balance', v_member.stamp_balance, 'points_balance', v_member.points_balance, 'reason', 'idempotent_replay');\n  end if;\n\n  if v_member.last_visit_at is not null and v_member.last_visit_at > v_now - interval '30 minutes' then\n    return jsonb_build_object('ok', true, 'already_recorded', true, 'member_id', v_member.id, 'stamp_balance', v_member.stamp_balance, 'points_balance', v_member.points_balance, 'reason', 'visit_debounce');\n  end if;\n\n  v_next_stamps := coalesce(v_member.stamp_balance, 0) + 1;\n  update public.mobile_vendor_loyalty_members\n  set stamp_balance = v_next_stamps,\n      lifetime_stamps = coalesce(lifetime_stamps, 0) + 1,\n      visits = coalesce(visits, 0) + 1,\n      last_visit_at = v_now,\n      updated_at = v_now\n  where tenant_org_id = _tenant_org_id and id = v_member.id;\n\n  insert into public.mobile_vendor_loyalty_activity (\n    tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after,\n    points_delta, points_balance_after, source, source_ref, metadata\n  ) values (\n    _tenant_org_id, v_member.id, v_member.contact_id, 'visit', 1, v_next_stamps,\n    0, coalesce(v_member.points_balance, 0), 'owner_action', v_visit_ref, '{}'::jsonb\n  );\n\n  select * into v_referral\n  from public.mobile_vendor_loyalty_referrals\n  where tenant_org_id = _tenant_org_id and friend_member_id = v_member.id\n  order by joined_at desc limit 1 for update;\n\n  if found then\n    if v_referral.first_purchase_at is null then\n      update public.mobile_vendor_loyalty_referrals\n      set status = 'purchase_confirmed',\n          first_purchase_at = v_now,\n          first_purchase_ref = v_visit_ref,\n          first_purchase_source = 'owner_action',\n          metadata = coalesce(metadata, '{}'::jsonb) || jsonb_build_object('first_purchase_confirmed_by', 'owner_action'),\n          updated_at = v_now\n      where id = v_referral.id;\n      v_referral.first_purchase_at := v_now;\n      v_first_purchase_recorded := true;\n      v_event := 'purchase_confirmed';\n    end if;\n\n    if v_referral.referrer_points_awarded_at is null then\n      select * into v_referrer\n      from public.mobile_vendor_loyalty_members\n      where tenant_org_id = _tenant_org_id and id = v_referral.referrer_member_id\n      for update;\n      if found and v_referrer.status = 'active' and v_referrer.id <> v_member.id then\n        v_points := greatest(1, least(1000, coalesce(_referral_points, 100)));\n        update public.mobile_vendor_loyalty_members\n        set points_balance = coalesce(points_balance, 0) + v_points,\n            lifetime_points = coalesce(lifetime_points, 0) + v_points,\n            updated_at = v_now\n        where tenant_org_id = _tenant_org_id and id = v_referrer.id;\n\n        insert into public.mobile_vendor_loyalty_activity (\n          tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after,\n          points_delta, points_balance_after, source, source_ref, metadata\n        ) values (\n          _tenant_org_id, v_referrer.id, v_referrer.contact_id, 'referral_purchase', 0, coalesce(v_referrer.stamp_balance, 0),\n          v_points, coalesce(v_referrer.points_balance, 0) + v_points, 'bring_a_friend', v_referral.id::text,\n          jsonb_build_object('friend_member_id', v_member.id, 'first_purchase_ref', v_visit_ref)\n        );\n\n        update public.mobile_vendor_loyalty_referrals\n        set status = 'purchase_confirmed', referrer_points_awarded = v_points,\n            referrer_points_awarded_at = v_now, updated_at = v_now\n        where id = v_referral.id;\n        v_event := 'referrer_points_awarded';\n      end if;\n    end if;\n\n    if not v_first_purchase_recorded and v_referral.welcome_reward_status = 'pending_return' and v_referral.first_purchase_at is not null and v_referral.first_purchase_at < v_now then\n      update public.mobile_vendor_loyalty_referrals\n      set status = 'welcome_ready', welcome_reward_status = 'ready',\n          welcome_unlocked_at = coalesce(welcome_unlocked_at, v_now), updated_at = v_now\n      where id = v_referral.id and welcome_reward_status = 'pending_return';\n\n      if found then\n        insert into public.mobile_vendor_loyalty_activity (\n          tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after,\n          points_delta, points_balance_after, source, source_ref, metadata\n        ) values (\n          _tenant_org_id, v_member.id, v_member.contact_id, 'welcome_reward_unlocked', 0, v_next_stamps,\n          0, coalesce(v_member.points_balance, 0), 'bring_a_friend', v_referral.id::text,\n          jsonb_build_object('reward', 'free_size_upgrade')\n        );\n        v_event := 'welcome_reward_unlocked';\n      end if;\n    end if;\n  end if;\n\n  return jsonb_build_object('ok', true, 'already_recorded', false, 'member_id', v_member.id,\n    'stamp_balance', v_next_stamps, 'points_balance', coalesce(v_member.points_balance, 0), 'referral_event', v_event);\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _member_id uuid, _visit_ref text, _referral_points integer"},{"name":"record_score_change","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.record_score_change()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF OLD.lead_score IS DISTINCT FROM NEW.lead_score THEN\n    INSERT INTO public.lead_score_history (\n      contact_id, tenant_org_id, previous_score, new_score,\n      score_type, change_reason, factors\n    ) VALUES (\n      NEW.id, NEW.tenant_org_id::uuid, OLD.lead_score, NEW.lead_score,\n      'total', 'Score recalculation',\n      jsonb_build_object(\n        'quality_score', NEW.quality_score,\n        'engagement_score', NEW.engagement_score,\n        'recency_score', NEW.recency_score\n      )\n    );\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"redeem_mobile_vendor_loyalty_reward","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.redeem_mobile_vendor_loyalty_reward(_tenant_org_id uuid, _member_id uuid, _milestone integer, _reward_label text, _redemption_ref text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_member public.mobile_vendor_loyalty_members%rowtype;\n  v_ref text := nullif(btrim(coalesce(_redemption_ref, '')), '');\n  v_milestone integer := greatest(2, least(20, coalesce(_milestone, 10)));\n  v_next integer;\n  v_now timestamptz := now();\nbegin\n  if v_ref is null then raise exception 'Redemption reference required'; end if;\n  select * into v_member from public.mobile_vendor_loyalty_members\n  where tenant_org_id = _tenant_org_id and id = _member_id for update;\n  if not found then raise exception 'Loyalty member not found'; end if;\n  if v_member.status <> 'active' then raise exception 'Loyalty membership is not active'; end if;\n\n  if exists (select 1 from public.mobile_vendor_loyalty_activity where tenant_org_id = _tenant_org_id and member_id = v_member.id and activity_type = 'reward_redeemed' and source = 'owner_action' and source_ref = v_ref) then\n    return jsonb_build_object('ok', true, 'already_redeemed', true, 'member_id', v_member.id, 'stamp_balance', v_member.stamp_balance);\n  end if;\n\n  v_next := coalesce(v_member.stamp_balance, 0) - v_milestone;\n  if v_next < 0 then raise exception 'Loyalty reward is not ready'; end if;\n\n  update public.mobile_vendor_loyalty_members\n  set stamp_balance = v_next, rewards_redeemed = coalesce(rewards_redeemed, 0) + 1, updated_at = v_now\n  where tenant_org_id = _tenant_org_id and id = v_member.id;\n\n  insert into public.mobile_vendor_loyalty_activity (\n    tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after,\n    points_delta, points_balance_after, source, source_ref, metadata\n  ) values (\n    _tenant_org_id, v_member.id, v_member.contact_id, 'reward_redeemed', -v_milestone, v_next,\n    0, coalesce(v_member.points_balance, 0), 'owner_action', v_ref,\n    jsonb_build_object('reward_label', coalesce(nullif(btrim(_reward_label), ''), 'Loyalty reward'))\n  );\n  return jsonb_build_object('ok', true, 'already_redeemed', false, 'member_id', v_member.id, 'stamp_balance', v_next);\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _member_id uuid, _milestone integer, _reward_label text, _redemption_ref text"},{"name":"redeem_mobile_vendor_referral_welcome_reward","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.redeem_mobile_vendor_referral_welcome_reward(_tenant_org_id uuid, _referral_id uuid, _redemption_ref text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_referral public.mobile_vendor_loyalty_referrals%rowtype;\n  v_member public.mobile_vendor_loyalty_members%rowtype;\n  v_now timestamptz := now();\n  v_ref text := nullif(btrim(coalesce(_redemption_ref, '')), '');\nbegin\n  if v_ref is null then raise exception 'Redemption reference required'; end if;\n  select * into v_referral from public.mobile_vendor_loyalty_referrals\n  where tenant_org_id = _tenant_org_id and id = _referral_id for update;\n  if not found then raise exception 'Referral reward not found'; end if;\n  if v_referral.welcome_reward_status = 'redeemed' then\n    return jsonb_build_object('ok', true, 'already_redeemed', true, 'referral_id', v_referral.id, 'member_id', v_referral.friend_member_id);\n  end if;\n  if v_referral.welcome_reward_status <> 'ready' then raise exception 'Referral welcome reward is not ready'; end if;\n\n  select * into v_member from public.mobile_vendor_loyalty_members\n  where tenant_org_id = _tenant_org_id and id = v_referral.friend_member_id for update;\n  if not found then raise exception 'Loyalty member not found'; end if;\n\n  update public.mobile_vendor_loyalty_referrals\n  set status = 'completed', welcome_reward_status = 'redeemed', welcome_redeemed_at = v_now,\n      metadata = coalesce(metadata, '{}'::jsonb) || jsonb_build_object('welcome_redemption_ref', v_ref), updated_at = v_now\n  where id = v_referral.id;\n\n  insert into public.mobile_vendor_loyalty_activity (\n    tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after,\n    points_delta, points_balance_after, source, source_ref, metadata\n  ) values (\n    _tenant_org_id, v_member.id, v_member.contact_id, 'welcome_reward_redeemed', 0, coalesce(v_member.stamp_balance, 0),\n    0, coalesce(v_member.points_balance, 0), 'bring_a_friend', v_ref,\n    jsonb_build_object('referral_id', v_referral.id, 'reward', 'free_size_upgrade')\n  );\n  return jsonb_build_object('ok', true, 'already_redeemed', false, 'referral_id', v_referral.id, 'member_id', v_member.id);\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _referral_id uuid, _redemption_ref text"},{"name":"refresh_onboarding_readiness","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.refresh_onboarding_readiness(p_session_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  s public.onboarding_sessions%rowtype; v_missing jsonb := '[]'::jsonb; v_pending int := 0; v_owner_review int := 0; v_operator_review int := 0; v_failed int := 0; v_result jsonb; v_status text; v_canonical_type text;\nBEGIN\n  SELECT * INTO s FROM public.onboarding_sessions WHERE id=p_session_id;\n  IF NOT FOUND THEN RAISE EXCEPTION 'Onboarding session not found'; END IF;\n  IF coalesce(auth.role(),'') <> 'service_role' THEN IF auth.uid() IS NULL OR (s.owner_user_id IS DISTINCT FROM auth.uid() AND NOT public.is_system_admin(auth.uid())) THEN RAISE EXCEPTION 'Not authorized for this onboarding session' USING ERRCODE='42501'; END IF; END IF;\n  v_canonical_type := public.canonical_tenant_type(s.requested_business_type);\n  IF v_canonical_type IS NULL THEN v_missing:=v_missing||jsonb_build_array('business_type'); END IF;\n  IF coalesce(s.company_name,'')='' THEN v_missing:=v_missing||jsonb_build_array('company_name'); END IF;\n  IF cardinality(s.operating_states)=0 THEN v_missing:=v_missing||jsonb_build_array('operating_states'); END IF;\n  IF coalesce(s.service_area->>'mode','')='' THEN v_missing:=v_missing||jsonb_build_array('service_area'); END IF;\n  IF coalesce(s.intake_answers->>'home_country','')='' THEN v_missing:=v_missing||jsonb_build_array('home_country'); END IF;\n  IF coalesce(s.intake_answers->>'owner_name','')='' AND coalesce(s.intake_answers->>'license_number','')='' THEN v_missing:=v_missing||jsonb_build_array('owner_name_or_license_number'); END IF;\n  SELECT count(*) INTO v_pending FROM public.onboarding_research_tasks WHERE session_id=p_session_id AND status IN ('pending','running');\n  SELECT count(*) INTO v_owner_review FROM public.onboarding_research_tasks WHERE session_id=p_session_id AND status IN ('needs_review','not_found') AND coalesce((result->>'owner_input_required')::boolean,false)=true;\n  SELECT count(*) INTO v_operator_review FROM public.onboarding_research_tasks WHERE session_id=p_session_id AND status IN ('needs_review','not_found') AND coalesce((result->>'owner_input_required')::boolean,false)=false;\n  SELECT count(*) INTO v_failed FROM public.onboarding_research_tasks WHERE session_id=p_session_id AND status='failed';\n  IF v_owner_review > 0 THEN v_missing:=v_missing||jsonb_build_array('owner_verification_input'); END IF;\n  v_status := CASE WHEN jsonb_array_length(v_missing)>0 THEN 'needs_input' WHEN v_pending>0 THEN 'researching' WHEN v_operator_review>0 OR v_failed>0 THEN 'validating' WHEN s.status IN ('provisioning','ready','live') THEN s.status ELSE 'ready_to_provision' END;\n  v_result:=jsonb_build_object('missing',v_missing,'research_pending',v_pending,'owner_input_required',v_owner_review,'operator_review',v_operator_review,'research_failed',v_failed,'ready',jsonb_array_length(v_missing)=0 AND v_pending=0);\n  UPDATE public.onboarding_sessions SET canonical_tenant_type=v_canonical_type,readiness=v_result,status=v_status,updated_at=now() WHERE id=p_session_id;\n  RETURN v_result;\nEND;\n$function$\n","identity_arguments":"p_session_id uuid"},{"name":"remove_pcg_demo_data","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.remove_pcg_demo_data(p_tenant_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$declare v_tasks int:=0;v_cards int:=0;v_submissions int:=0;v_opportunities int:=0;begin if not(is_tenant_member(auth.uid(),p_tenant_id) or is_system_admin(auth.uid())) then raise exception 'tenant access required';end if;delete from public.pcg_growth_tasks where tenant_id=p_tenant_id and is_demo=true;get diagnostics v_tasks=row_count;delete from public.card_grading_cards where tenant_id=p_tenant_id and is_demo=true;get diagnostics v_cards=row_count;delete from public.card_grading_submissions where tenant_id=p_tenant_id and is_demo=true;get diagnostics v_submissions=row_count;delete from public.opportunity_radar_opportunities where tenant_id=p_tenant_id and coalesce((metadata->>'demo')::boolean,false)=true;get diagnostics v_opportunities=row_count;return jsonb_build_object('tasks',v_tasks,'cards',v_cards,'submissions',v_submissions,'opportunities',v_opportunities);end$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"request_user_id","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.request_user_id()\n RETURNS uuid\n LANGUAGE plpgsql\n STABLE\n SET search_path TO ''\nAS $function$\ndeclare\n  v_sub text := nullif(current_setting('request.jwt.claim.sub', true), '');\n  v_claims text;\nbegin\n  if v_sub is null then\n    v_claims := nullif(current_setting('request.jwt.claims', true), '');\n    if v_claims is not null then\n      v_sub := nullif((v_claims::jsonb) ->> 'sub', '');\n    end if;\n  end if;\n\n  if v_sub is null then\n    return null;\n  end if;\n\n  begin\n    return v_sub::uuid;\n  exception\n    when invalid_text_representation then\n      return null;\n  end;\nend;\n$function$\n","identity_arguments":""},{"name":"require_platform_operator","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.require_platform_operator()\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\ndeclare\n  v_role text := nullif(current_setting('request.jwt.claim.role', true), '');\n  v_claims text;\nbegin\n  if v_role is null then\n    v_claims := nullif(current_setting('request.jwt.claims', true), '');\n    if v_claims is not null then\n      v_role := nullif((v_claims::jsonb) ->> 'role', '');\n    end if;\n  end if;\n\n  if coalesce(v_role, '') = 'service_role' then\n    return;\n  end if;\n\n  if public.request_user_id() is null\n     or not coalesce(public.is_platform_admin(public.request_user_id()), false) then\n    raise exception 'platform administrator authorization required'\n      using errcode = '42501';\n  end if;\nend;\n$function$\n","identity_arguments":""},{"name":"reserve_big_papis_proposal_number","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.reserve_big_papis_proposal_number(p_tenant_id uuid, p_year integer)\n RETURNS text\n LANGUAGE sql\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT public.reserve_proposal_number(p_tenant_id, 'BP', p_year);\n$function$\n","identity_arguments":"p_tenant_id uuid, p_year integer"},{"name":"reserve_proposal_number","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.reserve_proposal_number(p_tenant_id uuid, p_prefix text, p_year integer)\n RETURNS text\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\ndeclare v_prefix text; v_next integer;\nbegin\n  v_prefix:=upper(regexp_replace(trim(coalesce(p_prefix,'')),'[^A-Z0-9]','','g'));\n  if v_prefix='' or length(v_prefix)>12 then raise exception 'invalid_proposal_prefix' using errcode='22023'; end if;\n  if p_year<2000 or p_year>2200 then raise exception 'invalid_proposal_year' using errcode='22023'; end if;\n  if coalesce(auth.role(),'')<>'service_role' and (auth.uid() is null or not public.is_tenant_member(auth.uid(),p_tenant_id)) then raise exception 'tenant_access_denied' using errcode='42501'; end if;\n  insert into public.proposal_sequences(tenant_id,proposal_year,number_prefix,last_sequence,updated_at)\n  values(p_tenant_id,p_year,v_prefix,1,now())\n  on conflict(tenant_id,proposal_year,number_prefix) do update set last_sequence=public.proposal_sequences.last_sequence+1,updated_at=now()\n  returning last_sequence into v_next;\n  return format('%s-%s-%s',v_prefix,p_year,lpad(v_next::text,3,'0'));\nend; $function$\n","identity_arguments":"p_tenant_id uuid, p_prefix text, p_year integer"},{"name":"reset_test_contact_to_workflow","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.reset_test_contact_to_workflow(p_contact_id uuid)\n RETURNS TABLE(id uuid, status text, contact_status text, graduated_at timestamp with time zone, archived_at timestamp with time zone, is_test_account boolean)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant uuid;\n  v_is_test boolean;\n  v_caller uuid := auth.uid();\nBEGIN\n  IF v_caller IS NULL THEN\n    RAISE EXCEPTION 'not_authenticated' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT uc.tenant_org_id, uc.is_test_account\n    INTO v_tenant, v_is_test\n  FROM public.unified_contacts uc\n  WHERE uc.id = p_contact_id;\n\n  IF v_tenant IS NULL THEN\n    RAISE EXCEPTION 'contact_not_found' USING ERRCODE = 'P0002';\n  END IF;\n\n  IF COALESCE(v_is_test, false) = false THEN\n    RAISE EXCEPTION 'not_a_test_contact' USING ERRCODE = '42501';\n  END IF;\n\n  -- Authorization: must be system admin OR manager+ in this tenant.\n  IF NOT (\n    public.is_system_admin()\n    OR public.is_manager_or_higher(v_caller, v_tenant)\n  ) THEN\n    RAISE EXCEPTION 'insufficient_privileges' USING ERRCODE = '42501';\n  END IF;\n\n  RETURN QUERY\n  UPDATE public.unified_contacts uc\n     SET graduated_at = NULL,\n         archived_at  = NULL,\n         status         = 'New',\n         contact_status = 'New',\n         lead_stage     = 'New / Unassigned',\n         updated_at     = now()\n   WHERE uc.id = p_contact_id\n     AND uc.is_test_account = true\n  RETURNING uc.id, uc.status, uc.contact_status, uc.graduated_at, uc.archived_at, uc.is_test_account;\nEND;\n$function$\n","identity_arguments":"p_contact_id uuid"},{"name":"resolve_command_center_tenant_reference","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.resolve_command_center_tenant_reference(_tenant_ref text)\n RETURNS TABLE(tenant_id uuid, tenant_name text, company_slug text, confidence double precision, match_kind text)\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'extensions', 'pg_catalog'\nAS $function$\n with input as (\n  select trim(coalesce(_tenant_ref,'')) raw_ref, public.command_center_normalize_tenant_ref(_tenant_ref) norm_ref,\n   replace(public.command_center_normalize_tenant_ref(_tenant_ref),' ','') compact_ref, public.command_center_tenant_acronym(_tenant_ref) acronym_ref\n ), alias_candidates as (\n  select t.id tenant_id,t.name tenant_name,t.company_slug,\n   case when a.normalized_alias=i.norm_ref then 0.998 else least(0.93,0.52+0.40*extensions.similarity(a.normalized_alias,i.norm_ref)) end confidence,\n   case when a.normalized_alias=i.norm_ref then 'learned_alias_exact' else 'learned_alias_fuzzy' end match_kind\n  from input i join public.command_center_tenant_aliases a on i.norm_ref<>'' and (a.normalized_alias=i.norm_ref or extensions.similarity(a.normalized_alias,i.norm_ref)>=0.55)\n  join public.tenants t on t.id=a.tenant_id where coalesce(t.status,'active')='active'\n ), tenant_base as (\n  select t.id,t.name,t.company_slug, public.command_center_normalize_tenant_ref(t.name) norm_name,\n   public.command_center_normalize_tenant_ref(t.company_slug) norm_slug,\n   replace(public.command_center_normalize_tenant_ref(t.name),' ','') compact_name,\n   replace(public.command_center_normalize_tenant_ref(t.company_slug),' ','') compact_slug,\n   public.command_center_tenant_acronym(t.name) acronym_name, public.command_center_tenant_acronym(t.company_slug) acronym_slug\n  from public.tenants t where coalesce(t.status,'active')='active'\n ), scored as (\n  select t.id tenant_id,t.name tenant_name,t.company_slug,best.confidence,best.match_kind\n  from input i join tenant_base t on i.norm_ref<>'' cross join lateral (\n   select v.confidence,v.match_kind from (values\n    (case when t.id::text=i.raw_ref then 1.0 else 0.0 end,'exact_id'::text),\n    (case when i.norm_ref=t.norm_name then 0.997 else 0.0 end,'exact_name'::text),\n    (case when i.norm_ref=t.norm_slug then 0.996 else 0.0 end,'exact_slug'::text),\n    (case when i.compact_ref<>'' and (i.compact_ref=t.compact_name or i.compact_ref=t.compact_slug) then 0.992 else 0.0 end,'normalized_exact'::text),\n    (case when length(i.norm_ref)>=3 and (t.norm_name like i.norm_ref||' %' or t.norm_slug like i.norm_ref||' %') then 0.968 else 0.0 end,'name_prefix'::text),\n    (case when length(i.compact_ref)>=4 and (t.compact_name like i.compact_ref||'%' or t.compact_slug like i.compact_ref||'%') then 0.958 else 0.0 end,'compact_prefix'::text),\n    (case when length(i.acronym_ref)>=2 and (i.acronym_ref=t.acronym_name or i.acronym_ref=t.acronym_slug) then 0.965 else 0.0 end,'acronym_exact'::text),\n    (case when length(i.acronym_ref)>=3 and greatest(length(t.acronym_name),length(t.acronym_slug))>=3 and least(\n      case when t.acronym_name='' then 99 else extensions.levenshtein(i.acronym_ref,t.acronym_name) end,\n      case when t.acronym_slug='' then 99 else extensions.levenshtein(i.acronym_ref,t.acronym_slug) end)<=1 then 0.925 else 0.0 end,'acronym_one_edit'::text),\n    (least(0.94,0.50+0.44*greatest(extensions.word_similarity(i.norm_ref,t.norm_name),extensions.word_similarity(i.norm_ref,t.norm_slug),extensions.word_similarity(t.norm_name,i.norm_ref),extensions.word_similarity(t.norm_slug,i.norm_ref))),'word_similarity'::text),\n    (least(0.90,0.46+0.42*greatest(extensions.similarity(i.norm_ref,t.norm_name),extensions.similarity(i.norm_ref,t.norm_slug),extensions.similarity(i.compact_ref,t.compact_name),extensions.similarity(i.compact_ref,t.compact_slug))),'trigram_similarity'::text)\n   ) v(confidence,match_kind) order by v.confidence desc limit 1\n  ) best where best.confidence>=0.55\n ), combined as (select * from alias_candidates union all select * from scored), deduped as (\n  select distinct on(tenant_id) tenant_id,tenant_name,company_slug,confidence,match_kind from combined order by tenant_id,confidence desc\n ) select tenant_id,tenant_name,company_slug,confidence,match_kind from deduped order by confidence desc,tenant_name asc limit 5;\n$function$\n","identity_arguments":"_tenant_ref text"},{"name":"retry_member_academy_onboarding","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.retry_member_academy_onboarding(p_user_id uuid, p_tenant_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_uid uuid := auth.uid();\nbegin\n  if v_uid is null then raise exception 'Authentication required' using errcode='42501'; end if;\n  if not (\n    public.is_system_admin(v_uid)\n    or public.is_tenant_owner_or_admin(v_uid,p_tenant_id)\n    or public.is_manager_or_higher(v_uid,p_tenant_id)\n    or (v_uid=p_user_id and public.is_tenant_member(v_uid,p_tenant_id))\n  ) then\n    raise exception 'Not authorized to retry Academy onboarding' using errcode='42501';\n  end if;\n  return public.ensure_academy_onboarding_for_member(p_user_id,p_tenant_id,v_uid);\nend;\n$function$\n","identity_arguments":"p_user_id uuid, p_tenant_id uuid"},{"name":"revert_call_designation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.revert_call_designation(p_call_log_id uuid)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user_id UUID := auth.uid();\n  v_log RECORD;\n  v_prev JSONB;\n  v_age_seconds NUMERIC;\nBEGIN\n  IF v_user_id IS NULL THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Authentication required');\n  END IF;\n\n  SELECT * INTO v_log FROM call_logs WHERE id = p_call_log_id LIMIT 1;\n  IF NOT FOUND THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Call log not found');\n  END IF;\n\n  IF v_log.user_id <> v_user_id THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Only the rep who logged this call can undo it');\n  END IF;\n\n  v_age_seconds := EXTRACT(EPOCH FROM (NOW() - v_log.created_at));\n  IF v_age_seconds > 30 THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'Undo window expired');\n  END IF;\n\n  v_prev := COALESCE(v_log.metadata->'previous_state', '{}'::jsonb);\n  IF v_prev = '{}'::jsonb THEN\n    RETURN jsonb_build_object('ok', false, 'error', 'No previous state recorded');\n  END IF;\n\n  -- Restore unified_contacts\n  UPDATE unified_contacts SET\n    status         = COALESCE(v_prev->>'status', status),\n    contact_status = COALESCE(v_prev->>'contact_status', contact_status),\n    lead_stage     = COALESCE(v_prev->>'lead_stage', lead_stage),\n    assigned_to    = COALESCE(v_prev->>'assigned_to', assigned_to),\n    assigned_rep   = COALESCE(v_prev->>'assigned_rep', assigned_rep),\n    appt_date      = NULLIF(v_prev->>'appt_date', ''),\n    appt_time      = NULLIF(v_prev->>'appt_time', ''),\n    graduated_at   = NULLIF(v_prev->>'graduated_at', '')::timestamptz,\n    jobs_stage     = NULLIF(v_prev->>'jobs_stage', ''),\n    claim_stage    = NULLIF(v_prev->>'claim_stage', ''),\n    deleted_at     = NULLIF(v_prev->>'deleted_at', '')::timestamptz,\n    notes          = COALESCE(v_prev->>'notes', notes),\n    updated_at     = NOW()\n  WHERE lead_id = v_log.lead_id AND tenant_org_id = v_log.tenant_id::text;\n\n  -- Mirror onto lead_deck\n  UPDATE lead_deck SET\n    status     = COALESCE(v_prev->>'status', status),\n    lead_stage = COALESCE(v_prev->>'lead_stage', lead_stage),\n    deleted_at = NULLIF(v_prev->>'deleted_at', '')::timestamptz,\n    updated_at = NOW()\n  WHERE lead_id = v_log.lead_id AND tenant_org_id = v_log.tenant_id::text;\n\n  -- Remove the follow-up created by this designation (if any was created same-second)\n  DELETE FROM followups\n  WHERE lead_id = v_log.lead_id\n    AND tenant_org_id = v_log.tenant_id::text\n    AND created_at >= v_log.created_at - INTERVAL '2 seconds'\n    AND status = 'Pending';\n\n  -- Roll back DNC entry if this call set it\n  IF v_log.outcome = 'dnc_requested' AND v_log.phone_called IS NOT NULL AND v_log.phone_called <> '' THEN\n    DELETE FROM dnc_list\n    WHERE phone = v_log.phone_called\n      AND tenant_org_id = v_log.tenant_id::text\n      AND created_at >= v_log.created_at - INTERVAL '2 seconds';\n  END IF;\n\n  -- Mark the call log as reverted (do NOT delete, keep audit trail)\n  UPDATE call_logs SET\n    metadata = COALESCE(metadata, '{}'::jsonb)\n               || jsonb_build_object(\n                    'reverted', true,\n                    'reverted_at', NOW(),\n                    'reverted_by', v_user_id\n                  ),\n    updated_at = NOW()\n  WHERE id = p_call_log_id;\n\n  RETURN jsonb_build_object(\n    'ok', true,\n    'lead_id', v_log.lead_id,\n    'restored_status', v_prev->>'status',\n    'restored_lead_stage', v_prev->>'lead_stage'\n  );\nEND;\n$function$\n","identity_arguments":"p_call_log_id uuid"},{"name":"review_mobile_vendor_loyalty_claim","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.review_mobile_vendor_loyalty_claim(_tenant_org_id uuid, _claim_id uuid, _reviewer_id uuid, _decision text, _bonus_stamps integer DEFAULT 1, _review_note text DEFAULT NULL::text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_claim public.mobile_vendor_loyalty_claims%rowtype;\n  v_member public.mobile_vendor_loyalty_members%rowtype;\n  v_bonus integer;\n  v_balance integer;\nbegin\n  if _decision not in ('approve', 'reject') then\n    raise exception 'Invalid loyalty claim decision';\n  end if;\n\n  select * into v_claim\n  from public.mobile_vendor_loyalty_claims\n  where tenant_org_id = _tenant_org_id and id = _claim_id\n  for update;\n\n  if not found then\n    raise exception 'Loyalty claim not found';\n  end if;\n\n  if v_claim.status in ('approved', 'rejected') then\n    return jsonb_build_object(\n      'ok', true,\n      'already_reviewed', true,\n      'status', v_claim.status,\n      'awarded_delta', v_claim.awarded_delta\n    );\n  end if;\n\n  if v_claim.status <> 'pending' then\n    raise exception 'Loyalty claim is not ready for review';\n  end if;\n\n  if _decision = 'reject' then\n    update public.mobile_vendor_loyalty_claims\n    set status = 'rejected', awarded_delta = 0, reviewed_by = _reviewer_id,\n        reviewed_at = now(), review_note = nullif(trim(coalesce(_review_note, '')), ''), updated_at = now()\n    where id = v_claim.id;\n\n    return jsonb_build_object('ok', true, 'status', 'rejected', 'awarded_delta', 0);\n  end if;\n\n  v_bonus := greatest(1, least(5, coalesce(_bonus_stamps, 1)));\n\n  select * into v_member\n  from public.mobile_vendor_loyalty_members\n  where tenant_org_id = _tenant_org_id and id = v_claim.member_id\n  for update;\n\n  if not found or v_member.status <> 'active' then\n    raise exception 'Active loyalty member not found';\n  end if;\n\n  v_balance := coalesce(v_member.stamp_balance, 0) + v_bonus;\n\n  update public.mobile_vendor_loyalty_members\n  set stamp_balance = v_balance,\n      lifetime_stamps = coalesce(lifetime_stamps, 0) + v_bonus,\n      updated_at = now()\n  where tenant_org_id = _tenant_org_id and id = v_member.id;\n\n  insert into public.mobile_vendor_loyalty_activity (\n    tenant_org_id, member_id, contact_id, activity_type, stamps_delta, balance_after, source, source_ref, metadata\n  ) values (\n    _tenant_org_id,\n    v_member.id,\n    v_member.contact_id,\n    'photo_bonus',\n    v_bonus,\n    v_balance,\n    'loyalty_photo_claim',\n    v_claim.id::text,\n    jsonb_build_object('claim_id', v_claim.id, 'reviewed_by', _reviewer_id)\n  );\n\n  update public.mobile_vendor_loyalty_claims\n  set status = 'approved', awarded_delta = v_bonus, reviewed_by = _reviewer_id,\n      reviewed_at = now(), review_note = nullif(trim(coalesce(_review_note, '')), ''), updated_at = now()\n  where id = v_claim.id;\n\n  return jsonb_build_object(\n    'ok', true,\n    'status', 'approved',\n    'awarded_delta', v_bonus,\n    'balance_after', v_balance\n  );\nend;\n$function$\n","identity_arguments":"_tenant_org_id uuid, _claim_id uuid, _reviewer_id uuid, _decision text, _bonus_stamps integer, _review_note text"},{"name":"revoke_customer_portal_when_claims_close","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.revoke_customer_portal_when_claims_close()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\ndeclare\n  v_contact_id text;\n  v_tenant_id text;\nbegin\n  if tg_op = 'DELETE' then\n    v_contact_id := old.contact_id;\n    v_tenant_id := old.tenant_org_id;\n  else\n    v_contact_id := new.contact_id;\n    v_tenant_id := new.tenant_org_id;\n  end if;\n\n  if not exists (\n    select 1\n    from public.contact_claims cc\n    where cc.contact_id = v_contact_id\n      and cc.tenant_org_id = v_tenant_id\n      and upper(trim(coalesce(cc.claim_stage, ''))) <> 'P7_CLOSE'\n  ) then\n    update public.customer_portal_access cpa\n    set\n      is_active = false,\n      expires_at = least(coalesce(cpa.expires_at, now()), now())\n    where cpa.contact_id = v_contact_id\n      and cpa.tenant_id = v_tenant_id\n      and cpa.is_active is true;\n  end if;\n\n  return coalesce(new, old);\nend;\n$function$\n","identity_arguments":""},{"name":"revoke_portal_links_on_archive","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.revoke_portal_links_on_archive()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.archived_at IS NOT NULL AND (OLD.archived_at IS NULL OR OLD.archived_at IS DISTINCT FROM NEW.archived_at) THEN\n    UPDATE public.portal_links\n       SET is_active = false\n     WHERE contact_id = NEW.id\n       AND is_active = true;\n  ELSIF NEW.archived_at IS NULL AND OLD.archived_at IS NOT NULL THEN\n    -- Restore portal links if contact is un-archived\n    UPDATE public.portal_links\n       SET is_active = true\n     WHERE contact_id = NEW.id\n       AND is_active = false;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"roofing_ops_can_manage","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.roofing_ops_can_manage(p_tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  select public.is_platform_admin(auth.uid())\n    or exists (\n      select 1\n      from public.user_tenant_access uta\n      where uta.user_id = auth.uid()\n        and uta.tenant_id = p_tenant_id\n        and coalesce(uta.membership_status, 'active') = 'active'\n        and coalesce(uta.effective_role, '') in (\n          'GodMode',\n          'Admin',\n          'Owner',\n          'Tenant Owner',\n          'Manager',\n          'OfficeAdmin',\n          'OFFICE_ADMIN',\n          'PM'\n        )\n    );\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"roofing_ops_can_read","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.roofing_ops_can_read(p_tenant_id uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  select public.is_platform_admin(auth.uid())\n    or exists (\n      select 1\n      from public.user_tenant_access uta\n      where uta.user_id = auth.uid()\n        and uta.tenant_id = p_tenant_id\n        and coalesce(uta.membership_status, 'active') = 'active'\n    );\n$function$\n","identity_arguments":"p_tenant_id uuid"},{"name":"roofing_ops_touch_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.roofing_ops_touch_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nbegin new.updated_at = now(); return new; end;\n$function$\n","identity_arguments":""},{"name":"run_pa_claim_automation_rules","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.run_pa_claim_automation_rules()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  rule_row record;\n  action_row jsonb;\n  cfg jsonb;\n  due_days integer;\n  assigned_user uuid;\nbegin\n  if new.claim_stage is not distinct from old.claim_stage then\n    return new;\n  end if;\n\n  select assigned_to into assigned_user\n  from public.unified_contacts\n  where id::text = new.contact_id::text\n  limit 1;\n\n  for rule_row in\n    select id, name, actions\n    from public.pipeline_automation_rules\n    where tenant_org_id::text = new.tenant_org_id::text\n      and is_active = true\n      and trigger_type = 'stage_change'\n      and coalesce(trigger_config ->> 'entity_kind', 'contact') = 'claim'\n      and (trigger_config ->> 'to_stage' is null or trigger_config ->> 'to_stage' = new.claim_stage)\n      and (trigger_config ->> 'from_stage' is null or trigger_config ->> 'from_stage' = old.claim_stage)\n    order by priority desc, created_at asc\n  loop\n    for action_row in select value from jsonb_array_elements(coalesce(rule_row.actions, '[]'::jsonb))\n    loop\n      cfg := coalesce(action_row -> 'config', action_row -> 'params', '{}'::jsonb);\n\n      if action_row ->> 'type' = 'create_claim_task' then\n        due_days := greatest(0, coalesce((cfg ->> 'due_in_days')::integer, 1));\n\n        if not exists (\n          select 1\n          from public.tasks t\n          where t.claim_id = new.id\n            and t.metadata ->> 'automation_rule_id' = rule_row.id::text\n            and t.metadata ->> 'claim_stage' = new.claim_stage\n            and t.status in ('pending', 'in_progress')\n        ) then\n          insert into public.tasks (\n            tenant_id,\n            user_id,\n            assigned_to,\n            contact_id,\n            claim_id,\n            title,\n            description,\n            priority,\n            status,\n            due_date,\n            metadata\n          ) values (\n            new.tenant_org_id,\n            assigned_user,\n            assigned_user,\n            new.contact_id,\n            new.id,\n            coalesce(cfg ->> 'title', rule_row.name),\n            cfg ->> 'description',\n            coalesce(cfg ->> 'priority', 'medium'),\n            'pending',\n            now() + make_interval(days => due_days),\n            jsonb_build_object(\n              'source', 'pa_claim_automation',\n              'automation_rule_id', rule_row.id,\n              'automation_rule_name', rule_row.name,\n              'claim_stage', new.claim_stage\n            )\n          );\n        end if;\n      end if;\n    end loop;\n\n    update public.pipeline_automation_rules\n    set execution_count = coalesce(execution_count, 0) + 1,\n        last_executed_at = now()\n    where id = rule_row.id;\n\n    insert into public.automation_run_log (\n      tenant_org_id,\n      rule_id,\n      rule_name,\n      engine,\n      trigger_type,\n      entity_kind,\n      entity_id,\n      status,\n      dry_run,\n      payload,\n      actions_executed\n    ) values (\n      new.tenant_org_id::uuid,\n      rule_row.id,\n      rule_row.name,\n      'pa-claim-stage-trigger',\n      'stage_change',\n      'claim',\n      new.id,\n      'success',\n      false,\n      jsonb_build_object('from_stage', old.claim_stage, 'to_stage', new.claim_stage, 'contact_id', new.contact_id),\n      rule_row.actions\n    );\n  end loop;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"save_my_onboarding_intake","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.save_my_onboarding_intake(p_session_id uuid DEFAULT NULL::uuid, p_company_name text DEFAULT NULL::text, p_business_type text DEFAULT NULL::text, p_service_lines jsonb DEFAULT NULL::jsonb, p_operating_states text[] DEFAULT NULL::text[], p_service_area jsonb DEFAULT NULL::jsonb, p_team_size integer DEFAULT NULL::integer, p_goals jsonb DEFAULT NULL::jsonb, p_requested_capabilities jsonb DEFAULT NULL::jsonb, p_intake_answers jsonb DEFAULT NULL::jsonb, p_email text DEFAULT NULL::text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_uid uuid := auth.uid();\n  v_session_id uuid;\n  v_email text;\n  s public.onboarding_sessions%rowtype;\nbegin\n  if v_uid is null then raise exception 'Authentication required' using errcode='42501'; end if;\n  select email into v_email from auth.users where id=v_uid;\n  v_email := coalesce(nullif(p_email,''),v_email);\n\n  if p_session_id is not null then\n    select id into v_session_id from public.onboarding_sessions\n    where id=p_session_id and (owner_user_id=v_uid or public.is_system_admin(v_uid));\n    if v_session_id is null then raise exception 'Onboarding session not found' using errcode='42501'; end if;\n  else\n    select id into v_session_id\n    from public.onboarding_sessions\n    where owner_user_id=v_uid and status not in ('live','cancelled')\n    order by updated_at desc\n    limit 1;\n  end if;\n\n  if v_session_id is null then\n    insert into public.onboarding_sessions(owner_user_id,email,company_name,status)\n    values(v_uid,v_email,coalesce(p_company_name,''),'draft')\n    returning id into v_session_id;\n  end if;\n\n  update public.onboarding_sessions\n  set email=coalesce(v_email,email),\n      company_name=coalesce(p_company_name,company_name),\n      requested_business_type=coalesce(p_business_type,requested_business_type),\n      service_lines=case when p_service_lines is null then service_lines else p_service_lines end,\n      operating_states=case when p_operating_states is null then operating_states else p_operating_states end,\n      service_area=case when p_service_area is null then service_area else p_service_area end,\n      team_size=coalesce(p_team_size,team_size),\n      goals=case when p_goals is null then goals else p_goals end,\n      requested_capabilities=case when p_requested_capabilities is null then requested_capabilities else p_requested_capabilities end,\n      intake_answers=coalesce(intake_answers,'{}'::jsonb) || coalesce(p_intake_answers,'{}'::jsonb),\n      last_error=null,\n      updated_at=now()\n  where id=v_session_id;\n\n  perform public.derive_onboarding_blueprint(v_session_id);\n  select * into s from public.onboarding_sessions where id=v_session_id;\n  if coalesce(s.requested_business_type,'')<>'' and cardinality(s.operating_states)>0 then\n    perform public.queue_onboarding_license_research(v_session_id);\n  else\n    perform public.refresh_onboarding_readiness(v_session_id);\n  end if;\n\n  return public.get_my_onboarding_context(v_session_id);\nend;\n$function$\n","identity_arguments":"p_session_id uuid, p_company_name text, p_business_type text, p_service_lines jsonb, p_operating_states text[], p_service_area jsonb, p_team_size integer, p_goals jsonb, p_requested_capabilities jsonb, p_intake_answers jsonb, p_email text"},{"name":"save_tenant_full_workflow_script","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.save_tenant_full_workflow_script(p_tenant_id uuid, p_tenant_type text, p_cards jsonb, p_rebuttals jsonb, p_change_notes text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_uid uuid := auth.uid();\n  v_email text;\n  v_type text;\n  v_full_key text;\n  v_override_key text;\n  v_card_count int;\n  v_rebuttal_count int;\n  v_saved_at timestamptz := now();\n  v_payload jsonb;\nBEGIN\n  IF v_uid IS NULL THEN\n    RAISE EXCEPTION 'Authentication required' USING ERRCODE = '42501';\n  END IF;\n\n  IF p_tenant_id IS NULL THEN\n    RAISE EXCEPTION 'tenant_id is required' USING ERRCODE = '22023';\n  END IF;\n\n  -- Permission gate: platform admin OR tenant owner/admin OR manager-in-tenant.\n  IF NOT (\n    public.is_system_admin(v_uid)\n    OR public.is_tenant_owner_or_admin(v_uid, p_tenant_id)\n    OR public.is_manager_or_higher(v_uid, p_tenant_id)\n  ) THEN\n    RAISE EXCEPTION 'You do not have permission to activate scripts for this tenant'\n      USING ERRCODE = '42501';\n  END IF;\n\n  -- Payload validation.\n  IF p_cards IS NULL OR jsonb_typeof(p_cards) <> 'array' OR jsonb_array_length(p_cards) = 0 THEN\n    RAISE EXCEPTION 'cards must be a non-empty JSON array' USING ERRCODE = '22023';\n  END IF;\n\n  v_card_count := jsonb_array_length(p_cards);\n  v_rebuttal_count := CASE\n    WHEN p_rebuttals IS NOT NULL AND jsonb_typeof(p_rebuttals) = 'array'\n      THEN jsonb_array_length(p_rebuttals)\n    ELSE 0\n  END;\n\n  v_type := upper(regexp_replace(coalesce(p_tenant_type, 'MITIGATION'), '\\s+', '_', 'g'));\n  v_full_key := 'workflow_full_' || v_type;\n  v_override_key := 'workflow_overrides_' || v_type;\n\n  SELECT email INTO v_email FROM auth.users WHERE id = v_uid;\n\n  v_payload := jsonb_build_object(\n    '_format', 'knocklaunch.script-bundle.v1',\n    'cards', p_cards,\n    'rebuttals', COALESCE(p_rebuttals, '[]'::jsonb),\n    'changeNotes', COALESCE(p_change_notes, ''),\n    'savedAt', to_jsonb(v_saved_at),\n    'savedBy', COALESCE(v_email, v_uid::text)\n  );\n\n  INSERT INTO public.site_config (\n    config_key, config_value, category, tenant_org_id, updated_by, updated_at\n  ) VALUES (\n    v_full_key, v_payload, 'workflow_full', p_tenant_id::text,\n    COALESCE(v_email, v_uid::text), v_saved_at\n  )\n  ON CONFLICT (config_key, tenant_org_id) DO UPDATE\n  SET config_value = EXCLUDED.config_value,\n      category     = EXCLUDED.category,\n      updated_by   = EXCLUDED.updated_by,\n      updated_at   = EXCLUDED.updated_at;\n\n  -- Stale sparse-override row is no longer authoritative — remove it.\n  DELETE FROM public.site_config\n  WHERE config_key = v_override_key\n    AND tenant_org_id = p_tenant_id::text;\n\n  RETURN jsonb_build_object(\n    'ok', true,\n    'savedAt', to_jsonb(v_saved_at),\n    'cardCount', v_card_count,\n    'rebuttalCount', v_rebuttal_count,\n    'tenantOrgId', p_tenant_id,\n    'tenantType', v_type\n  );\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_tenant_type text, p_cards jsonb, p_rebuttals jsonb, p_change_notes text"},{"name":"scrub_lead_against_dnc","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.scrub_lead_against_dnc()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_normalized text;\n  v_match RECORD;\n  v_quarantined BOOLEAN;\nBEGIN\n  IF TG_OP = 'UPDATE' AND NEW.phone IS NOT DISTINCT FROM OLD.phone AND OLD.is_dnc = NEW.is_dnc THEN\n    RETURN NEW;\n  END IF;\n\n  v_normalized := public.normalize_phone_for_dnc(NEW.phone);\n  IF v_normalized IS NULL THEN\n    NEW.dnc_checked_at := now();\n    NEW.is_dnc := false;\n    RETURN NEW;\n  END IF;\n\n  -- Block if previously quarantined\n  SELECT EXISTS(SELECT 1 FROM public.dnc_quarantine WHERE phone_normalized = v_normalized)\n    INTO v_quarantined;\n  IF v_quarantined THEN\n    RAISE EXCEPTION 'Phone % is in DNC quarantine vault and cannot be re-imported.', NEW.phone;\n  END IF;\n\n  SELECT phone, reason INTO v_match\n  FROM public.dnc_list WHERE phone_normalized = v_normalized LIMIT 1;\n\n  NEW.dnc_checked_at := now();\n  IF v_match.phone IS NOT NULL THEN\n    NEW.is_dnc := true;\n    NEW.dnc_reason := COALESCE(v_match.reason, 'Matched DNC list');\n    NEW.status := 'DNC';\n  ELSE\n    NEW.is_dnc := false;\n    NEW.dnc_reason := NULL;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"search_contacts","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.search_contacts(search_query text, tenant_id text DEFAULT NULL::text)\n RETURNS TABLE(id text, name text, phone text, email text, address text, city text, state text, status text, rank real)\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  RETURN QUERY\n  SELECT uc.id, uc.name, uc.phone, uc.email, uc.address, uc.city, uc.state, uc.status,\n    ts_rank(to_tsvector('english', coalesce(uc.name, '') || ' ' || coalesce(uc.email, '') || ' ' || coalesce(uc.phone, '') || ' ' || coalesce(uc.address, '') || ' ' || coalesce(uc.city, '') || ' ' || coalesce(uc.notes, '')), plainto_tsquery('english', search_query)) as rank\n  FROM unified_contacts uc\n  WHERE (tenant_id IS NULL OR uc.tenant_org_id = tenant_id) AND uc.deleted_at IS NULL\n    AND to_tsvector('english', coalesce(uc.name, '') || ' ' || coalesce(uc.email, '') || ' ' || coalesce(uc.phone, '') || ' ' || coalesce(uc.address, '') || ' ' || coalesce(uc.city, '') || ' ' || coalesce(uc.notes, '')) @@ plainto_tsquery('english', search_query)\n  ORDER BY rank DESC LIMIT 100;\nEND;\n$function$\n","identity_arguments":"search_query text, tenant_id text"},{"name":"security_remove_roles_for_inactive_membership","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.security_remove_roles_for_inactive_membership()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_user_id uuid;\n  v_tenant_id uuid;\n  v_remove boolean := false;\nBEGIN\n  IF TG_OP = 'DELETE' THEN\n    v_user_id := OLD.user_id;\n    v_tenant_id := OLD.tenant_id;\n    v_remove := true;\n  ELSE\n    v_user_id := NEW.user_id;\n    v_tenant_id := NEW.tenant_id;\n    v_remove := coalesce(NEW.status, '') <> 'active';\n  END IF;\n\n  IF v_remove THEN\n    DELETE FROM public.user_roles ur\n    WHERE ur.user_id = v_user_id\n      AND ur.tenant_id = v_tenant_id;\n  END IF;\n\n  RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;\nEND;\n$function$\n","identity_arguments":""},{"name":"security_validate_role_scope_update","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.security_validate_role_scope_update()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF NEW.tenant_id IS NOT NULL\n     AND NOT EXISTS (\n       SELECT 1\n       FROM public.user_tenant_memberships m\n       WHERE m.user_id = NEW.user_id\n         AND m.tenant_id = NEW.tenant_id\n         AND m.status = 'active'\n     ) THEN\n    RAISE EXCEPTION 'scoped role requires active tenant membership' USING ERRCODE = '42501';\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"seed_default_automation_on_tenant_create","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.seed_default_automation_on_tenant_create()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  PERFORM public.ensure_default_homeowner_stage_rule(NEW.id);\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"seed_roofing_invoice_templates","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.seed_roofing_invoice_templates()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\ndeclare\n  v_body text := '<section class=\"roofing-invoice\"><header><h1>{{company_name}}</h1><p>Roofing Invoice</p></header><p><strong>Invoice:</strong> {{invoice_number}}</p><p><strong>Homeowner:</strong> {{customer_name}}</p><p><strong>Property:</strong> {{property_address}}</p><div>{{line_items}}</div><p><strong>Subtotal:</strong> {{subtotal}}</p><p><strong>Tax:</strong> {{tax}}</p><p><strong>Total due:</strong> {{total}}</p><p><strong>Due date:</strong> {{due_date}}</p><footer>{{payment_instructions}}</footer></section>';\n  v_variables jsonb := '[\"company_name\",\"invoice_number\",\"customer_name\",\"property_address\",\"line_items\",\"subtotal\",\"tax\",\"total\",\"due_date\",\"payment_instructions\"]'::jsonb;\nbegin\n  if upper(replace(coalesce(new.tenant_type, ''), ' ', '_')) <> 'ROOFING_COMPANY' then\n    return new;\n  end if;\n\n  insert into public.invoice_templates (tenant_id, key, label, tone, body, variables, is_default)\n  values\n    (new.id, 'roofing_invoice', 'Roofing Invoice', 'vertical', v_body, v_variables, true),\n    (new.id, 'roofing', 'Roofing Invoice', 'vertical', v_body, v_variables, false),\n    (new.id, 'standard', 'Standard Invoice', 'standard', v_body, v_variables, false)\n  on conflict (tenant_id, key) do update\n    set body = case\n          when length(btrim(public.invoice_templates.body)) = 0 then excluded.body\n          else public.invoice_templates.body\n        end,\n        variables = case\n          when public.invoice_templates.variables = '[]'::jsonb then excluded.variables\n          else public.invoice_templates.variables\n        end,\n        updated_at = now();\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"seed_statutory_deadlines","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.seed_statutory_deadlines()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _dol DATE;\nBEGIN\n  -- Skip if no DOL or DOL not parseable\n  IF NEW.date_of_loss IS NULL OR NEW.date_of_loss = '' THEN\n    RETURN NEW;\n  END IF;\n\n  BEGIN\n    _dol := NEW.date_of_loss::DATE;\n  EXCEPTION WHEN OTHERS THEN\n    RETURN NEW;\n  END;\n\n  -- Only seed if no deadlines exist yet for this claim\n  IF EXISTS (SELECT 1 FROM public.claim_deadlines WHERE claim_id = NEW.id) THEN\n    RETURN NEW;\n  END IF;\n\n  -- 14-day acknowledgement (FL §627.70131(1)(a)) - measured from claim filing, default to today\n  INSERT INTO public.claim_deadlines (claim_id, contact_id, tenant_org_id, code, label, due_date, is_statutory)\n  VALUES (NEW.id, NEW.contact_id, NEW.tenant_org_id, 'ACK_14D', 'Carrier acknowledgement (14 days)', CURRENT_DATE + INTERVAL '14 days', true);\n\n  -- 60-day coverage decision (post-2022 FL reform §627.70131(7))\n  INSERT INTO public.claim_deadlines (claim_id, contact_id, tenant_org_id, code, label, due_date, is_statutory)\n  VALUES (NEW.id, NEW.contact_id, NEW.tenant_org_id, 'DECISION_60D', 'Coverage decision (60 days)', CURRENT_DATE + INTERVAL '60 days', true);\n\n  -- 1-year notice of claim (FL §627.70132 — post-2022 reform)\n  INSERT INTO public.claim_deadlines (claim_id, contact_id, tenant_org_id, code, label, due_date, is_statutory)\n  VALUES (NEW.id, NEW.contact_id, NEW.tenant_org_id, 'NOTICE_1Y', 'Notice of new/reopened claim (1 year from DOL)', _dol + INTERVAL '1 year', true);\n\n  -- 5-year statute of limitations on suit (FL §95.11(2)(e))\n  INSERT INTO public.claim_deadlines (claim_id, contact_id, tenant_org_id, code, label, due_date, is_statutory)\n  VALUES (NEW.id, NEW.contact_id, NEW.tenant_org_id, 'SOL_5Y', 'Statute of limitations on suit (5 years from DOL)', _dol + INTERVAL '5 years', true);\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"set_communication_events_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.set_communication_events_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"set_contact_compliance_bypass","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.set_contact_compliance_bypass(_tenant_org_id text, _contact_id uuid, _enabled boolean, _reason text)\n RETURNS TABLE(active boolean, audit_event_id uuid, checked_at timestamp with time zone)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_user uuid := auth.uid();\n  v_tenant_uuid uuid;\n  v_can_bypass boolean := false;\n  v_contact record;\n  v_previous_active boolean := false;\n  v_event_id uuid;\n  v_checked_at timestamptz;\n  v_reason text := btrim(COALESCE(_reason, ''));\nBEGIN\n  IF v_user IS NULL THEN\n    RAISE EXCEPTION 'Authentication required';\n  END IF;\n\n  IF _tenant_org_id IS NULL OR _contact_id IS NULL THEN\n    RAISE EXCEPTION 'Tenant and contact are required';\n  END IF;\n\n  BEGIN\n    v_tenant_uuid := _tenant_org_id::uuid;\n  EXCEPTION WHEN others THEN\n    v_tenant_uuid := NULL;\n  END;\n\n  v_can_bypass := public.is_system_admin(v_user)\n    OR (v_tenant_uuid IS NOT NULL AND public.is_admin_or_higher(v_user, v_tenant_uuid));\n\n  IF NOT v_can_bypass THEN\n    RAISE EXCEPTION 'Only tenant owners/admins can bypass compliance gates';\n  END IF;\n\n  SELECT uc.id, uc.tenant_org_id, uc.phone, uc.normalized_phone, uc.is_test_account\n  INTO v_contact\n  FROM public.unified_contacts uc\n  WHERE uc.id = _contact_id\n    AND uc.tenant_org_id = _tenant_org_id;\n\n  IF NOT FOUND THEN\n    RAISE EXCEPTION 'Contact not found in active tenant';\n  END IF;\n\n  IF v_contact.is_test_account IS DISTINCT FROM true THEN\n    RAISE EXCEPTION 'Compliance bypass is limited to test contacts';\n  END IF;\n\n  IF char_length(v_reason) < 5 THEN\n    RAISE EXCEPTION 'Reason must be at least 5 characters';\n  END IF;\n\n  SELECT COALESCE(ce.result = 'bypass_enabled', false)\n  INTO v_previous_active\n  FROM public.communication_compliance_events ce\n  WHERE ce.tenant_org_id = _tenant_org_id\n    AND ce.lead_id = _contact_id::text\n    AND ce.check_type = 'owner_bypass'\n  ORDER BY ce.checked_at DESC\n  LIMIT 1;\n\n  v_previous_active := COALESCE(v_previous_active, false);\n\n  INSERT INTO public.communication_compliance_events AS cce (\n    tenant_org_id,\n    lead_id,\n    phone_number,\n    phone_normalized,\n    check_type,\n    provider,\n    result,\n    decision,\n    reason,\n    raw_response,\n    checked_by\n  ) VALUES (\n    _tenant_org_id,\n    _contact_id::text,\n    COALESCE(v_contact.phone, v_contact.normalized_phone, 'N/A'),\n    v_contact.normalized_phone,\n    'owner_bypass',\n    'owner_manual_override',\n    CASE WHEN _enabled THEN 'bypass_enabled' ELSE 'bypass_disabled' END,\n    'override',\n    v_reason,\n    jsonb_build_object(\n      'action', CASE WHEN _enabled THEN 'bypass_enabled' ELSE 'bypass_disabled' END,\n      'previous_state', CASE WHEN v_previous_active THEN 'gates_bypassed' ELSE 'gates_active' END,\n      'new_state', CASE WHEN _enabled THEN 'gates_bypassed' ELSE 'gates_active' END,\n      'previous_active', v_previous_active,\n      'new_active', _enabled,\n      'contact_id', _contact_id,\n      'tenant_org_id', _tenant_org_id,\n      'user_id', v_user\n    ),\n    v_user\n  )\n  RETURNING cce.id, cce.checked_at INTO v_event_id, v_checked_at;\n\n  RETURN QUERY SELECT _enabled, v_event_id, v_checked_at;\nEND;\n$function$\n","identity_arguments":"_tenant_org_id text, _contact_id uuid, _enabled boolean, _reason text"},{"name":"set_door_created_by","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.set_door_created_by()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  IF NEW.created_by IS NULL THEN\n    NEW.created_by = auth.uid();\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"set_updated_at_simple","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.set_updated_at_simple()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$ BEGIN NEW.updated_at = now(); RETURN NEW; END $function$\n","identity_arguments":""},{"name":"set_vm_drop_month_bucket","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.set_vm_drop_month_bucket()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.month_bucket := to_char(NEW.dropped_at AT TIME ZONE 'UTC','YYYY-MM');\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"shares_tenant_as_manager_pm","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.shares_tenant_as_manager_pm(_viewer uuid, _target uuid)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1\n    FROM public.user_tenant_memberships utm_target\n    WHERE utm_target.user_id = _target\n      AND utm_target.status = 'active'\n      AND public.is_manager_pm_or_higher(_viewer, utm_target.tenant_id)\n  )\n$function$\n","identity_arguments":"_viewer uuid, _target uuid"},{"name":"sync_321_lockout_signed_agreement","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_321_lockout_signed_agreement()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  request_id uuid;\nbegin\n  if new.template_type <> '321_auto_unlock_service_authorization'\n     or new.status <> 'signed'\n     or old.status is not distinct from 'signed' then\n    return new;\n  end if;\n\n  if coalesce(new.variables ->> 'LOCKOUT_REQUEST_ID', '') !~* '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' then\n    return new;\n  end if;\n\n  request_id := (new.variables ->> 'LOCKOUT_REQUEST_ID')::uuid;\n\n  update public.vehicle_lockout_requests\n     set ownership_confirmed = coalesce(new.variables ->> 'AUTHORITY_BASIS_CODE', '') = 'registered_owner',\n         authorization_consented = true,\n         authorization_name = coalesce(new.signer_name, authorization_name),\n         authorization_at = coalesce(new.signed_at, now()),\n         authorization_signed_at = coalesce(new.signed_at, now()),\n         authorization_agreement_id = new.id,\n         status = case when status = 'awaiting_signature' then 'requested' else status end,\n         updated_at = now()\n   where id = request_id\n     and tenant_id = new.tenant_id;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"sync_lead_score_to_contact","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_lead_score_to_contact()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.subject_type = 'contact' AND NEW.score_type = 'stormscore' THEN\n    UPDATE public.unified_contacts\n    SET lead_score = NEW.score\n    WHERE id = NEW.subject_id\n      AND (lead_score IS DISTINCT FROM NEW.score);\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"sync_linked_contacts","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_linked_contacts()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_link_group UUID;\n  v_shared_fields_changed BOOLEAN;\n  v_claim_stage_changed BOOLEAN;\n  v_linked_tenant RECORD;\n  v_member RECORD;\n  v_actor_name TEXT;\nBEGIN\n  -- Check if any shared core field actually changed\n  -- NOTE: claim_stage is PUBLIC (shared), jobs_stage is PRIVATE (not shared)\n  v_shared_fields_changed := (\n    OLD.name IS DISTINCT FROM NEW.name OR\n    OLD.first_name IS DISTINCT FROM NEW.first_name OR\n    OLD.last_name IS DISTINCT FROM NEW.last_name OR\n    OLD.phone IS DISTINCT FROM NEW.phone OR\n    OLD.email IS DISTINCT FROM NEW.email OR\n    OLD.address IS DISTINCT FROM NEW.address OR\n    OLD.city IS DISTINCT FROM NEW.city OR\n    OLD.state IS DISTINCT FROM NEW.state OR\n    OLD.zip IS DISTINCT FROM NEW.zip OR\n    OLD.claim_stage IS DISTINCT FROM NEW.claim_stage\n  );\n\n  v_claim_stage_changed := (OLD.claim_stage IS DISTINCT FROM NEW.claim_stage);\n\n  IF NOT v_shared_fields_changed THEN\n    RETURN NEW;\n  END IF;\n\n  -- Find the link group for this contact\n  SELECT link_group_id INTO v_link_group\n  FROM contact_links\n  WHERE contact_id = NEW.id\n  LIMIT 1;\n\n  IF v_link_group IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  -- Get actor name for notifications\n  IF v_claim_stage_changed THEN\n    SELECT name INTO v_actor_name FROM profiles WHERE id = auth.uid() LIMIT 1;\n  END IF;\n\n  -- Propagate shared fields to all other contacts in the same link group\n  -- IMPORTANT: jobs_stage is NOT included — it stays private per tenant\n  UPDATE unified_contacts uc\n  SET\n    name = NEW.name,\n    first_name = NEW.first_name,\n    last_name = NEW.last_name,\n    phone = NEW.phone,\n    email = NEW.email,\n    address = NEW.address,\n    city = NEW.city,\n    state = NEW.state,\n    zip = NEW.zip,\n    claim_stage = NEW.claim_stage,\n    updated_at = now()\n  FROM contact_links cl\n  WHERE cl.link_group_id = v_link_group\n    AND cl.contact_id = uc.id\n    AND cl.contact_id != NEW.id;\n\n  -- If claim_stage changed, notify all users in linked tenants\n  IF v_claim_stage_changed THEN\n    FOR v_linked_tenant IN\n      SELECT cl.tenant_id, cl.contact_id\n      FROM contact_links cl\n      WHERE cl.link_group_id = v_link_group\n        AND cl.contact_id != NEW.id\n    LOOP\n      FOR v_member IN\n        SELECT utm.user_id\n        FROM user_tenant_memberships utm\n        WHERE utm.tenant_id = v_linked_tenant.tenant_id\n          AND utm.status = 'active'\n      LOOP\n        INSERT INTO notification_queue (\n          user_id, title, message, notification_type, severity, metadata, created_at\n        ) VALUES (\n          v_member.user_id,\n          'Claim Stage Updated',\n          COALESCE(NEW.name, 'Contact') || ' claim stage changed to: ' || COALESCE(NEW.claim_stage, 'Unknown'),\n          'shared_contact_update',\n          'info',\n          jsonb_build_object(\n            'link_group_id', v_link_group,\n            'contact_id', v_linked_tenant.contact_id,\n            'source_contact_id', NEW.id,\n            'field', 'claim_stage',\n            'old_value', OLD.claim_stage,\n            'new_value', NEW.claim_stage,\n            'actor_name', v_actor_name,\n            'contact_name', NEW.name\n          ),\n          now()\n        );\n      END LOOP;\n    END LOOP;\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"sync_membership_to_role","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_membership_to_role()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_role public.app_role;\nBEGIN\n  IF coalesce(NEW.status, '') <> 'active' THEN\n    DELETE FROM public.user_roles ur\n    WHERE ur.user_id = NEW.user_id\n      AND ur.tenant_id = NEW.tenant_id;\n    RETURN NEW;\n  END IF;\n\n  v_role := (CASE WHEN coalesce(NEW.is_owner,false) THEN 'Tenant Owner' ELSE 'Rep' END)::public.app_role;\n  INSERT INTO public.user_roles(user_id, tenant_id, role)\n  VALUES (NEW.user_id, NEW.tenant_id, v_role)\n  ON CONFLICT (user_id,tenant_id) DO UPDATE\n    SET role = CASE\n      WHEN excluded.role = 'Tenant Owner'::public.app_role\n       AND public.user_roles.role = 'Rep'::public.app_role\n      THEN excluded.role\n      ELSE public.user_roles.role\n    END;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"sync_mobile_vendor_event_expenses_to_finance","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_mobile_vendor_event_expenses_to_finance()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\ndeclare\n  is_mobile_vendor boolean := false;\n  expense_key text;\n  expense_label text;\n  raw_amount text;\n  expense_amount numeric(12,2);\n  external_id text;\nbegin\n  select coalesce(settings->>'workspace_type','') = 'mobile_vendor' or company_slug = 'big-papis'\n    into is_mobile_vendor\n  from public.tenants\n  where id = new.tenant_org_id;\n\n  if not coalesce(is_mobile_vendor, false) then\n    return new;\n  end if;\n\n  for expense_key, expense_label in\n    select * from (values\n      ('rental','Rental'),\n      ('product','Product'),\n      ('fuel','Fuel'),\n      ('food','Food'),\n      ('other','Other')\n    ) as expense_categories(key, label)\n  loop\n    raw_amount := trim(coalesce(new.expenses->>expense_key, ''));\n    expense_amount := case\n      when raw_amount ~ '^([0-9]+([.][0-9]{1,2})?|[.][0-9]{1,2})$' then raw_amount::numeric\n      else 0\n    end;\n    external_id := 'event:' || new.id::text || ':expense:' || expense_key;\n\n    if expense_amount > 0 then\n      insert into public.finance_transactions (\n        tenant_id, source, provider, provider_external_id, transaction_date, posted_at,\n        merchant, description, amount, direction, transaction_type, category,\n        classification, notes, receipt_document_ref, metadata, created_by, updated_at\n      ) values (\n        new.tenant_org_id,\n        'mobile_vendor_event_expense',\n        'manual',\n        external_id,\n        coalesce(new.event_date, current_date),\n        now(),\n        coalesce((select company_dba_name from public.tenants where id = new.tenant_org_id), (select name from public.tenants where id = new.tenant_org_id), 'Mobile vendor'),\n        coalesce(new.event_name, 'Event') || ' · ' || expense_label || ' expense',\n        expense_amount,\n        'expense',\n        'event_expense',\n        expense_label,\n        'business',\n        null,\n        null,\n        jsonb_build_object('record_class','business','event_booking_id',new.id,'expense_key',expense_key),\n        null,\n        now()\n      )\n      on conflict (tenant_id, source, provider_external_id)\n      do update set transaction_date=excluded.transaction_date, posted_at=excluded.posted_at,\n        merchant=excluded.merchant, description=excluded.description, amount=excluded.amount,\n        category=excluded.category, metadata=excluded.metadata, updated_at=now();\n    else\n      delete from public.finance_transactions\n      where tenant_id=new.tenant_org_id and source='mobile_vendor_event_expense' and provider_external_id=external_id;\n    end if;\n  end loop;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"sync_profile_role_from_user_roles","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_profile_role_from_user_roles()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE v_user_id uuid; v_new_primary text; v_old_primary text;\nBEGIN\n  v_user_id := COALESCE(NEW.user_id, OLD.user_id);\n  IF v_user_id IS NULL THEN RETURN COALESCE(NEW, OLD); END IF;\n  v_new_primary := public.compute_primary_role_for_user(v_user_id);\n  SELECT role INTO v_old_primary FROM public.profiles WHERE id = v_user_id;\n  UPDATE public.profiles\n  SET role = COALESCE(v_new_primary, 'Rep'), updated_at = now()\n  WHERE id = v_user_id\n    AND COALESCE(role, '') IS DISTINCT FROM COALESCE(v_new_primary, 'Rep');\n  IF COALESCE(v_old_primary, '') IS DISTINCT FROM COALESCE(v_new_primary, 'Rep') THEN\n    INSERT INTO public.comprehensive_audit_logs (\n      user_id, tenant_id, event_type, event_category, event_action,\n      resource_type, resource_id, old_value, new_value, severity, human_summary\n    ) VALUES (\n      auth.uid(), COALESCE(NEW.tenant_id, OLD.tenant_id),\n      'role_change', 'security', lower(TG_OP) || '_user_role',\n      'user_roles', v_user_id::text,\n      jsonb_build_object('role', v_old_primary),\n      jsonb_build_object('role', v_new_primary),\n      'warn',\n      'Primary role for user ' || v_user_id::text || ' changed: ' ||\n        COALESCE(v_old_primary, '(none)') || ' -> ' || COALESCE(v_new_primary, '(none)')\n    );\n  END IF;\n  RETURN COALESCE(NEW, OLD);\nEND;\n$function$\n","identity_arguments":""},{"name":"sync_role_to_membership","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_role_to_membership()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nbegin\n  -- Global/platform roles intentionally have tenant_id = NULL.\n  -- user_tenant_memberships.tenant_id is NOT NULL, so do not sync global roles.\n  if new.tenant_id is null then\n    return new;\n  end if;\n\n  insert into public.user_tenant_memberships (\n    user_id,\n    tenant_id,\n    is_owner,\n    status\n  )\n  values (\n    new.user_id,\n    new.tenant_id,\n    new.role::text in ('Owner', 'Tenant Owner', 'GodMode', 'Admin'),\n    'active'\n  )\n  on conflict (user_id, tenant_id) do update\n    set status = 'active',\n        is_owner = excluded.is_owner or public.user_tenant_memberships.is_owner;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"sync_tenant_is_trial","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_tenant_is_trial()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF TG_OP = 'INSERT' THEN\n    UPDATE public.tenants SET is_trial = true, trial_account_id = NEW.id WHERE id = NEW.tenant_id;\n  ELSIF TG_OP = 'DELETE' THEN\n    UPDATE public.tenants SET is_trial = false, trial_account_id = NULL WHERE id = OLD.tenant_id;\n  END IF;\n  RETURN COALESCE(NEW, OLD);\nEND;\n$function$\n","identity_arguments":""},{"name":"sync_to_unified_inbox","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.sync_to_unified_inbox(p_tenant_id uuid, p_contact_id uuid, p_channel text, p_direction text, p_subject text, p_body text, p_from_address text, p_to_address text, p_external_id text DEFAULT NULL::text, p_metadata jsonb DEFAULT '{}'::jsonb)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_inbox_id UUID;\n  v_preview TEXT;\nBEGIN\n  v_preview := LEFT(REGEXP_REPLACE(p_body, '<[^>]+>', '', 'g'), 100);\n  \n  INSERT INTO public.unified_inbox (\n    tenant_id, contact_id, channel, direction, subject, body, preview,\n    from_address, to_address, external_id, metadata,\n    sent_at, is_read\n  ) VALUES (\n    p_tenant_id, p_contact_id, p_channel, p_direction, p_subject, p_body, v_preview,\n    p_from_address, p_to_address, p_external_id, p_metadata,\n    CASE WHEN p_direction = 'outbound' THEN now() ELSE NULL END,\n    p_direction = 'outbound'\n  ) RETURNING id INTO v_inbox_id;\n  \n  RETURN v_inbox_id;\nEND;\n$function$\n","identity_arguments":"p_tenant_id uuid, p_contact_id uuid, p_channel text, p_direction text, p_subject text, p_body text, p_from_address text, p_to_address text, p_external_id text, p_metadata jsonb"},{"name":"system_backup_authorize","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_authorize(p_token text)\n RETURNS boolean\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public', 'vault', 'extensions'\nAS $function$\n  select coalesce((\n    select extensions.digest(ds.decrypted_secret, 'sha256') = extensions.digest(coalesce(p_token,''), 'sha256')\n    from vault.decrypted_secrets ds\n    where ds.name = 'knocklaunch_system_backup_trigger'\n    limit 1\n  ), false);\n$function$\n","identity_arguments":"p_token text"},{"name":"system_backup_catalog_snapshot","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_catalog_snapshot()\n RETURNS jsonb\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public', 'private', 'auth', 'storage', 'supabase_migrations', 'extensions'\n SET statement_timeout TO '60s'\nAS $function$\n  select jsonb_build_object(\n    'format','knocklaunch-database-catalog-v1','captured_at',now(),'database',current_database(),'server_version',current_setting('server_version'),\n    'extensions',(select coalesce(jsonb_agg(jsonb_build_object('name',e.extname,'version',e.extversion) order by e.extname),'[]'::jsonb) from pg_extension e),\n    'tables',(\n      select coalesce(jsonb_agg(jsonb_build_object(\n        'schema',n.nspname,'table',c.relname,\n        'columns',(select coalesce(jsonb_agg(jsonb_build_object('name',a.attname,'type',pg_catalog.format_type(a.atttypid,a.atttypmod),'not_null',a.attnotnull,'default',pg_get_expr(ad.adbin,ad.adrelid),'identity',a.attidentity,'generated',a.attgenerated) order by a.attnum),'[]'::jsonb) from pg_attribute a left join pg_attrdef ad on ad.adrelid=a.attrelid and ad.adnum=a.attnum where a.attrelid=c.oid and a.attnum>0 and not a.attisdropped),\n        'constraints',(select coalesce(jsonb_agg(jsonb_build_object('name',con.conname,'definition',pg_get_constraintdef(con.oid,true)) order by con.conname),'[]'::jsonb) from pg_constraint con where con.conrelid=c.oid),\n        'indexes',(select coalesce(jsonb_agg(jsonb_build_object('name',ci.relname,'definition',pg_get_indexdef(ci.oid)) order by ci.relname),'[]'::jsonb) from pg_index ix join pg_class ci on ci.oid=ix.indexrelid where ix.indrelid=c.oid),\n        'triggers',(select coalesce(jsonb_agg(jsonb_build_object('name',tg.tgname,'definition',pg_get_triggerdef(tg.oid,true)) order by tg.tgname),'[]'::jsonb) from pg_trigger tg where tg.tgrelid=c.oid and not tg.tgisinternal),\n        'policies',(select coalesce(jsonb_agg(to_jsonb(p) order by p.policyname),'[]'::jsonb) from pg_policies p where p.schemaname=n.nspname and p.tablename=c.relname)\n      ) order by n.nspname,c.relname),'[]'::jsonb)\n      from pg_class c join pg_namespace n on n.oid=c.relnamespace\n      where c.relkind='r' and n.nspname in ('public','private','auth','storage','supabase_migrations')\n        and not (n.nspname='public' and c.relname in ('system_backup_runs','system_backup_items'))\n    ),\n    'views',(select coalesce(jsonb_agg(jsonb_build_object('schema',n.nspname,'name',c.relname,'definition',pg_get_viewdef(c.oid,true)) order by n.nspname,c.relname),'[]'::jsonb) from pg_class c join pg_namespace n on n.oid=c.relnamespace where c.relkind in ('v','m') and n.nspname in ('public','private','auth','storage')),\n    'routines',(select coalesce(jsonb_agg(jsonb_build_object('schema',n.nspname,'name',p.proname,'identity_arguments',pg_get_function_identity_arguments(p.oid),'definition',pg_get_functiondef(p.oid)) order by n.nspname,p.proname,pg_get_function_identity_arguments(p.oid)),'[]'::jsonb) from pg_proc p join pg_namespace n on n.oid=p.pronamespace where n.nspname in ('public','private') and p.prokind in ('f','p')),\n    'cron_jobs',(select coalesce(jsonb_agg(jsonb_build_object('jobname',j.jobname,'schedule',j.schedule,'command',j.command,'active',j.active) order by j.jobid),'[]'::jsonb) from cron.job j),\n    'vault_secret_names',(select coalesce(jsonb_agg(jsonb_build_object('name',s.name,'description',s.description) order by s.name),'[]'::jsonb) from vault.secrets s),\n    'migration_history',(select coalesce(jsonb_agg(jsonb_build_object('version',m.version,'name',m.name) order by m.version),'[]'::jsonb) from supabase_migrations.schema_migrations m)\n  );\n$function$\n","identity_arguments":""},{"name":"system_backup_export_chunk","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_export_chunk(p_item_id bigint)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'private', 'auth', 'storage', 'supabase_migrations'\nAS $function$\ndeclare\n  i public.system_backup_items%rowtype;\n  v_data jsonb;\n  v_rows integer;\nbegin\n  select * into i from public.system_backup_items where id=p_item_id;\n  if i.id is null or i.kind<>'database_chunk' then raise exception 'backup_item_not_database_chunk'; end if;\n  if i.source_schema not in ('public','private','auth','storage','supabase_migrations') then raise exception 'backup_schema_not_allowed'; end if;\n  if i.source_schema='public' and i.source_table in ('system_backup_runs','system_backup_items') then raise exception 'backup_internal_table_excluded'; end if;\n  if coalesce(i.row_limit,0)=0 then v_data:='[]'::jsonb;\n  else\n    execute format('select coalesce(jsonb_agg(to_jsonb(t)), ''[]''::jsonb) from (select * from %I.%I order by ctid offset %s limit %s) t',i.source_schema,i.source_table,coalesce(i.row_offset,0),i.row_limit) into v_data;\n  end if;\n  v_rows:=jsonb_array_length(v_data);\n  return jsonb_build_object('format','knocklaunch-table-chunk-v1','schema',i.source_schema,'table',i.source_table,'offset',coalesce(i.row_offset,0),'limit',coalesce(i.row_limit,0),'rows',v_rows,'data',v_data);\nend;\n$function$\n","identity_arguments":"p_item_id bigint"},{"name":"system_backup_lease_items","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_lease_items(p_run_id uuid, p_limit integer DEFAULT 1)\n RETURNS SETOF system_backup_items\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  with picked as (\n    select i.id from public.system_backup_items i\n    where i.run_id=p_run_id and ((i.status='pending' and i.next_attempt_at<=now()) or (i.status='processing' and i.lease_until<now()))\n    order by case i.kind when 'database_catalog' then 0 when 'database_chunk' then 1 else 2 end,i.id\n    for update skip locked limit greatest(1,least(coalesce(p_limit,1),10))\n  )\n  update public.system_backup_items i\n  set status='processing',attempts=i.attempts+1,lease_until=now()+interval '6 minutes',started_at=coalesce(i.started_at,now()),updated_at=now(),error=null\n  from picked where i.id=picked.id returning i.*;\n$function$\n","identity_arguments":"p_run_id uuid, p_limit integer"},{"name":"system_backup_prepare","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_prepare(p_trigger_source text DEFAULT 'manual'::text, p_source_main_sha text DEFAULT NULL::text, p_force boolean DEFAULT false, p_chunk_rows integer DEFAULT 500)\n RETURNS uuid\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'private', 'auth', 'storage', 'supabase_migrations', 'extensions'\nAS $function$\ndeclare\n  v_run_id uuid;\n  v_existing uuid;\n  v_migration_head text;\n  v_database_bytes bigint;\n  v_storage_count bigint;\n  v_storage_bytes bigint;\n  v_count bigint;\n  v_offset bigint;\n  v_chunk integer := greatest(100, least(coalesce(p_chunk_rows, 500), 2000));\n  r record;\nbegin\n  if not p_force then\n    select id into v_existing from public.system_backup_runs\n    where status in ('preparing','running','verifying') and requested_at > now() - interval '24 hours'\n    order by requested_at desc limit 1;\n    if v_existing is not null then return v_existing; end if;\n  end if;\n\n  select version || ' ' || name into v_migration_head from supabase_migrations.schema_migrations order by version desc limit 1;\n  select pg_database_size(current_database())::bigint into v_database_bytes;\n  select count(*)::bigint,\n         coalesce(sum(case when (metadata->>'size') ~ '^[0-9]+$' then (metadata->>'size')::bigint else 0 end),0)::bigint\n    into v_storage_count, v_storage_bytes from storage.objects;\n\n  insert into public.system_backup_runs(trigger_source, started_at, status, source_main_sha, migration_head, database_bytes, storage_object_count, storage_bytes, metadata)\n  values (\n    left(coalesce(nullif(trim(p_trigger_source),''),'manual'),80), now(), 'preparing', nullif(trim(coalesce(p_source_main_sha,'')),''), v_migration_head,\n    v_database_bytes, v_storage_count, v_storage_bytes,\n    jsonb_build_object('format','knocklaunch-full-data-backup-v1','database_consistency','best_effort_logical_plus_supabase_native_physical','schemas',jsonb_build_array('public','private','auth','storage','supabase_migrations'),'storage_objects_included',true,'secret_values_included',false,'secret_names_cataloged',true,'chunk_rows',v_chunk)\n  ) returning id into v_run_id;\n\n  insert into public.system_backup_items(run_id, kind, row_offset, row_limit, metadata)\n  values (v_run_id, 'database_catalog', 0, 1, jsonb_build_object('format','catalog-v1'));\n\n  for r in\n    select n.nspname as schema_name, c.relname as table_name\n    from pg_class c join pg_namespace n on n.oid=c.relnamespace\n    where c.relkind='r' and n.nspname in ('public','private','auth','storage','supabase_migrations')\n      and not (n.nspname='public' and c.relname in ('system_backup_runs','system_backup_items'))\n    order by n.nspname,c.relname\n  loop\n    execute format('select count(*)::bigint from %I.%I',r.schema_name,r.table_name) into v_count;\n    if v_count=0 then\n      insert into public.system_backup_items(run_id,kind,source_schema,source_table,row_offset,row_limit,metadata)\n      values(v_run_id,'database_chunk',r.schema_name,r.table_name,0,0,jsonb_build_object('table_rows_at_prepare',0));\n    else\n      v_offset:=0;\n      while v_offset<v_count loop\n        insert into public.system_backup_items(run_id,kind,source_schema,source_table,row_offset,row_limit,metadata)\n        values(v_run_id,'database_chunk',r.schema_name,r.table_name,v_offset,v_chunk,jsonb_build_object('table_rows_at_prepare',v_count));\n        v_offset:=v_offset+v_chunk;\n      end loop;\n    end if;\n  end loop;\n\n  insert into public.system_backup_items(run_id,kind,source_bucket,source_object,source_object_id,source_updated_at,source_size,source_fingerprint,artifact_key,metadata)\n  select v_run_id,'storage_object',o.bucket_id,o.name,o.id::text,coalesce(o.updated_at,o.created_at,now()),\n    case when (o.metadata->>'size') ~ '^[0-9]+$' then (o.metadata->>'size')::bigint else 0 end,\n    encode(extensions.digest(concat_ws('|',o.bucket_id,o.id::text,coalesce(o.updated_at,o.created_at)::text,coalesce(o.metadata->>'size','0'),coalesce(o.metadata->>'mimetype','')),'sha256'),'hex'),\n    'blobs/storage/'||regexp_replace(o.bucket_id,'[^a-zA-Z0-9._-]+','-','g')||'/'||o.id::text||'/'||\n      encode(extensions.digest(concat_ws('|',o.bucket_id,o.id::text,coalesce(o.updated_at,o.created_at)::text,coalesce(o.metadata->>'size','0'),coalesce(o.metadata->>'mimetype','')),'sha256'),'hex'),\n    jsonb_build_object('mime_type',o.metadata->>'mimetype')\n  from storage.objects o;\n\n  update public.system_backup_runs\n  set item_count=(select count(*) from public.system_backup_items where run_id=v_run_id), status='running'\n  where id=v_run_id;\n  return v_run_id;\nexception when others then\n  if v_run_id is not null then update public.system_backup_runs set status='failed',completed_at=now(),error=left(sqlerrm,2000) where id=v_run_id; end if;\n  raise;\nend;\n$function$\n","identity_arguments":"p_trigger_source text, p_source_main_sha text, p_force boolean, p_chunk_rows integer"},{"name":"system_backup_r2_identity","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_r2_identity()\n RETURNS jsonb\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'public', 'vault'\nAS $function$\n  select coalesce((select decrypted_secret::jsonb from vault.decrypted_secrets where name='knocklaunch_system_backup_r2_identity' limit 1),'{}'::jsonb);\n$function$\n","identity_arguments":""},{"name":"system_backup_store_r2_identity","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.system_backup_store_r2_identity(p_account_id text, p_api_token text)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'vault'\nAS $function$\ndeclare\n  v_id uuid;\n  v_payload text;\nbegin\n  if coalesce(length(trim(p_account_id)),0) <> 32 then raise exception 'backup_r2_account_id_invalid'; end if;\n  if coalesce(length(trim(p_api_token)),0) < 40 then raise exception 'backup_r2_token_invalid'; end if;\n  v_payload := jsonb_build_object('accountId',trim(p_account_id),'apiToken',trim(p_api_token))::text;\n  select id into v_id from vault.secrets where name='knocklaunch_system_backup_r2_identity' limit 1;\n  if v_id is null then\n    perform vault.create_secret(v_payload,'knocklaunch_system_backup_r2_identity','Dedicated Cloudflare R2 object token for KNOCKLAUNCH full backups.');\n  else\n    perform vault.update_secret(v_id,v_payload,'knocklaunch_system_backup_r2_identity','Dedicated Cloudflare R2 object token for KNOCKLAUNCH full backups.');\n  end if;\nend;\n$function$\n","identity_arguments":"p_account_id text, p_api_token text"},{"name":"tenant_allowed_zips","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tenant_allowed_zips(_tenant_id uuid)\n RETURNS text[]\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\n  SELECT ta.allowed_zip_codes\n  FROM public.trial_accounts ta\n  WHERE ta.tenant_id = _tenant_id\n    AND (\n      coalesce(auth.role(), '') = 'service_role'\n      OR public.is_system_admin(auth.uid())\n      OR public.is_tenant_member(auth.uid(), _tenant_id)\n    )\n  LIMIT 1;\n$function$\n","identity_arguments":"_tenant_id uuid"},{"name":"tenant_provider_secrets_touch_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tenant_provider_secrets_touch_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"test_activity_logging","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.test_activity_logging()\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_activity_id UUID;\n  v_security_count INT;\n  v_activity_count INT;\nBEGIN\n  -- Try to log a test activity\n  v_activity_id := public.log_user_activity(\n    'system_test',\n    'Activity Logging Test',\n    'Testing that activity logging is functioning correctly',\n    NULL,\n    jsonb_build_object('test', true, 'timestamp', NOW())\n  );\n  \n  -- Count recent logs\n  SELECT COUNT(*) INTO v_security_count \n  FROM security_events \n  WHERE timestamp > NOW() - INTERVAL '24 hours';\n  \n  SELECT COUNT(*) INTO v_activity_count \n  FROM activity_log \n  WHERE created_at > NOW() - INTERVAL '24 hours';\n  \n  RETURN jsonb_build_object(\n    'ok', true,\n    'test_activity_id', v_activity_id,\n    'security_events_24h', v_security_count,\n    'activity_logs_24h', v_activity_count,\n    'timestamp', NOW()\n  );\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_create_job_request_from_signed_work_auth","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_create_job_request_from_signed_work_auth()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_creator uuid;\nBEGIN\n  IF NEW.agreement_type IS DISTINCT FROM 'work_authorization' THEN\n    RETURN NEW;\n  END IF;\n  IF NEW.status IS DISTINCT FROM 'signed' THEN\n    RETURN NEW;\n  END IF;\n  IF NEW.tenant_id IS NULL THEN\n    RETURN NEW;\n  END IF;\n\n  -- Idempotency via existing UNIQUE(source_signed_agreement_id)\n  IF EXISTS (SELECT 1 FROM public.job_requests WHERE source_signed_agreement_id = NEW.id) THEN\n    RETURN NEW;\n  END IF;\n\n  v_creator := COALESCE(NEW.user_id, auth.uid());\n  IF v_creator IS NULL THEN\n    -- Job_requests requires created_by NOT NULL; fall back to a tenant owner\n    SELECT ur.user_id INTO v_creator\n      FROM public.user_roles ur\n     WHERE ur.tenant_id = NEW.tenant_id\n       AND ur.role IN ('Tenant Owner','Owner','Admin')\n     LIMIT 1;\n  END IF;\n\n  IF v_creator IS NULL THEN\n    RAISE WARNING '[work_auth->job_request] no creator resolvable for tenant %', NEW.tenant_id;\n    RETURN NEW;\n  END IF;\n\n  INSERT INTO public.job_requests (\n    tenant_id, contact_id, source_signed_agreement_id, source_kind,\n    created_by, job_type, scope, priority,\n    property_address, city, state, zip, status, notes\n  ) VALUES (\n    NEW.tenant_id,\n    NEW.contact_id,\n    NEW.id,\n    'signed_work_auth',\n    v_creator,\n    COALESCE(NEW.metadata->>'job_type', 'tarp'),\n    NEW.metadata->>'scope',\n    COALESCE(NEW.metadata->>'priority', 'normal'),\n    NEW.metadata->>'property_address',\n    NEW.metadata->>'city',\n    NEW.metadata->>'state',\n    NEW.metadata->>'zip',\n    'pending_review',\n    'Auto-created from signed Work Authorization ('||NEW.id||')'\n  )\n  ON CONFLICT (source_signed_agreement_id) DO NOTHING;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_door_notes_stamp_edited","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_door_notes_stamp_edited()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.author_id <> OLD.author_id\n     OR NEW.door_id <> OLD.door_id\n     OR NEW.tenant_org_id <> OLD.tenant_org_id\n     OR NEW.created_at <> OLD.created_at THEN\n    RAISE EXCEPTION 'Immutable fields on door_notes cannot be changed';\n  END IF;\n  NEW.edited_at := now();\n  NEW.updated_at := now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_door_status_to_timeline","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_door_status_to_timeline()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  INSERT INTO public.activity_timeline (\n    tenant_org_id, user_id, activity_type, title, description,\n    related_entity_id, related_entity_type, importance, is_system_generated, metadata\n  ) VALUES (\n    NEW.tenant_org_id,\n    NEW.actor_id,\n    'door_status_change',\n    'Door status: ' || COALESCE(NEW.previous_status, 'new') || ' → ' || NEW.new_status,\n    COALESCE(NEW.actor_name, 'A team member') || ' updated a door',\n    NEW.door_id,\n    'door',\n    'normal',\n    true,\n    jsonb_build_object('source', NEW.source, 'visit_id', NEW.visit_id)\n  );\n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_legal_pages_set_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_legal_pages_set_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_notify_managers_on_new_job_request","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_notify_managers_on_new_job_request()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant   tenant_organizations%ROWTYPE;\n  v_contact  unified_contacts%ROWTYPE;\n  v_link     text;\n  v_addr     text;\n  v_name     text;\n  v_title    text := 'New Job Request Pending Review';\n  v_msg_base text;\nBEGIN\n  IF NEW.status IS DISTINCT FROM 'pending_review' THEN\n    RETURN NEW;\n  END IF;\n\n  SELECT * INTO v_tenant FROM public.tenant_organizations WHERE id = NEW.tenant_id;\n  IF NOT FOUND THEN RETURN NEW; END IF;\n\n  IF NEW.contact_id IS NOT NULL THEN\n    SELECT * INTO v_contact FROM public.unified_contacts WHERE id = NEW.contact_id;\n  END IF;\n\n  v_name := COALESCE(v_contact.name, 'Customer');\n  v_addr := COALESCE(NEW.property_address, '(no address)');\n\n  v_link := '/crm/' || COALESCE(v_tenant.tenant_type, 'MITIGATION')\n            || '/' || COALESCE(v_tenant.company_slug, v_tenant.id::text)\n            || '/job-requests';\n\n  v_msg_base := 'A signed Work Authorization is ready for manager review — '\n                || v_name || ' · ' || v_addr\n                || ' · ' || COALESCE(NEW.job_type, 'job');\n\n  -- Write to notification_queue (read by NotificationCenter bell)\n  INSERT INTO public.notification_queue\n    (user_id, notification_type, title, message, severity, action_url, metadata)\n  SELECT\n    ur.user_id,\n    'job_request_pending',\n    v_title,\n    v_msg_base,\n    'info',\n    v_link,\n    jsonb_build_object(\n      'job_request_id', NEW.id,\n      'tenant_id', NEW.tenant_id,\n      'signed_agreement_id', NEW.source_signed_agreement_id,\n      'contact_id', NEW.contact_id,\n      'contact_name', v_name,\n      'property_address', NEW.property_address,\n      'job_type', NEW.job_type,\n      'created_at', NEW.created_at\n    )\n  FROM public.user_roles ur\n  WHERE ur.tenant_id = NEW.tenant_id\n    AND ur.role IN ('Manager','Admin','Tenant Owner','Owner')\n  ON CONFLICT (user_id, notification_type, ((metadata->>'job_request_id')))\n    WHERE notification_type = 'job_request_pending'\n    DO NOTHING;\n\n  -- Also keep legacy notifications table populated for any other consumers\n  INSERT INTO public.notifications (user_id, tenant_id, type, title, message, link, metadata)\n  SELECT\n    ur.user_id,\n    NEW.tenant_id::text,\n    'job_request_pending',\n    v_title,\n    v_msg_base,\n    v_link,\n    jsonb_build_object(\n      'job_request_id', NEW.id,\n      'tenant_id', NEW.tenant_id,\n      'contact_name', v_name,\n      'property_address', NEW.property_address,\n      'job_type', NEW.job_type\n    )\n  FROM public.user_roles ur\n  WHERE ur.tenant_id = NEW.tenant_id\n    AND ur.role IN ('Manager','Admin','Tenant Owner','Owner')\n  ON CONFLICT (user_id, type, ((metadata->>'job_request_id')))\n    WHERE type = 'job_request_pending'\n    DO NOTHING;\n\n  RETURN NEW;\nEXCEPTION WHEN OTHERS THEN\n  RAISE WARNING '[notify_managers_on_new_job_request] failed: %', SQLERRM;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_pending_voicemail_drops_touch","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_pending_voicemail_drops_touch()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_set_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_set_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at := now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_sync_enrollment_progress","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_sync_enrollment_progress()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF TG_OP = 'DELETE' THEN\n    PERFORM public.recalc_academy_enrollment_progress(OLD.user_id, OLD.course_id);\n    RETURN OLD;\n  ELSE\n    PERFORM public.recalc_academy_enrollment_progress(NEW.user_id, NEW.course_id);\n    RETURN NEW;\n  END IF;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_sync_pa_engagement_from_pending_agreement","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_sync_pa_engagement_from_pending_agreement()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_pa  public.pa_engagements%ROWTYPE;\n  v_new_status text;\n  v_now timestamptz := now();\n  v_doc_type text := 'Letter of Representation';\n  v_signed_path text;\n  v_status_changed boolean;\n  v_path_just_set boolean;\nBEGIN\n  v_status_changed := (TG_OP = 'INSERT')\n    OR (TG_OP = 'UPDATE' AND NEW.status IS DISTINCT FROM OLD.status);\n  v_path_just_set := (TG_OP = 'UPDATE'\n    AND NEW.status = 'signed'\n    AND NEW.signed_pdf_path IS NOT NULL\n    AND OLD.signed_pdf_path IS DISTINCT FROM NEW.signed_pdf_path);\n\n  -- Only act when something material changed for sync purposes\n  IF NOT (v_status_changed OR v_path_just_set) THEN\n    RETURN NEW;\n  END IF;\n\n  SELECT * INTO v_pa\n    FROM public.pa_engagements\n   WHERE pending_agreement_id = NEW.id\n   LIMIT 1;\n\n  IF NOT FOUND THEN\n    RETURN NEW; -- not PA-linked (e.g. SCETARPING work_auth) -> no-op\n  END IF;\n\n  v_new_status := CASE NEW.status\n    WHEN 'sent'    THEN 'Sent'\n    WHEN 'viewed'  THEN 'Viewed'\n    WHEN 'signed'  THEN 'Signed'\n    WHEN 'voided'  THEN 'Cancelled'\n    WHEN 'expired' THEN 'Cancelled'\n    ELSE NULL\n  END;\n\n  -- Status update path (or already-signed + path arrived)\n  IF v_new_status IS NOT NULL OR v_path_just_set THEN\n    UPDATE public.pa_engagements\n       SET status        = COALESCE(v_new_status, status),\n           sent_at       = COALESCE(sent_at,     NEW.sent_at),\n           viewed_at     = COALESCE(viewed_at,   NEW.viewed_at),\n           signed_at     = CASE WHEN NEW.status = 'signed'  THEN COALESCE(signed_at,    NEW.signed_at, v_now) ELSE signed_at END,\n           cancelled_at  = CASE WHEN NEW.status IN ('voided','expired') THEN COALESCE(cancelled_at, v_now) ELSE cancelled_at END,\n           signed_document_url = CASE WHEN NEW.status = 'signed' AND NEW.signed_pdf_path IS NOT NULL\n                                      THEN COALESCE(signed_document_url, NEW.signed_pdf_path)\n                                      ELSE signed_document_url END,\n           updated_at    = v_now\n     WHERE id = v_pa.id;\n  END IF;\n\n  -- Mirror to PA document checklist on signed (status change OR path arrival)\n  IF NEW.status = 'signed' AND v_pa.claim_id IS NOT NULL THEN\n    v_signed_path := NEW.signed_pdf_path;\n\n    IF EXISTS (\n      SELECT 1 FROM public.case_documents_required\n       WHERE tenant_org_id = v_pa.tenant_org_id::text\n         AND claim_id      = v_pa.claim_id\n         AND document_type = v_doc_type\n    ) THEN\n      UPDATE public.case_documents_required\n         SET status         = 'Verified',\n             linked_file_id = COALESCE(linked_file_id, v_signed_path),\n             linked_file_url= COALESCE(linked_file_url, v_signed_path),\n             verified_at    = COALESCE(verified_at, v_now),\n             notes          = COALESCE(notes, '') || CASE WHEN COALESCE(notes,'') = '' THEN '' ELSE E'\\n' END\n                              || 'Auto-verified via KnockLaunch Sign ('||NEW.id||')',\n             updated_at     = v_now\n       WHERE tenant_org_id = v_pa.tenant_org_id::text\n         AND claim_id      = v_pa.claim_id\n         AND document_type = v_doc_type;\n    ELSE\n      INSERT INTO public.case_documents_required (\n        tenant_org_id, claim_id, document_type, status,\n        linked_file_id, linked_file_url, verified_at, notes\n      ) VALUES (\n        v_pa.tenant_org_id::text, v_pa.claim_id, v_doc_type, 'Verified',\n        v_signed_path, v_signed_path, v_now,\n        'Auto-created via KnockLaunch Sign ('||NEW.id||')'\n      );\n    END IF;\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_sync_profile_last_login","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_sync_profile_last_login()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.last_sign_in_at IS DISTINCT FROM OLD.last_sign_in_at\n     AND NEW.last_sign_in_at IS NOT NULL THEN\n    UPDATE public.profiles\n    SET last_login = NEW.last_sign_in_at,\n        last_login_at = NEW.last_sign_in_at\n    WHERE id = NEW.id;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_uce_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_uce_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN NEW.updated_at = now(); RETURN NEW; END;\n$function$\n","identity_arguments":""},{"name":"tg_unified_contacts_mirror_assigned","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_unified_contacts_mirror_assigned()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF TG_OP = 'INSERT' THEN\n    IF NEW.assigned_to IS NOT NULL AND NEW.assigned_user IS NULL THEN\n      NEW.assigned_user := NEW.assigned_to;\n    ELSIF NEW.assigned_user IS NOT NULL AND NEW.assigned_to IS NULL THEN\n      NEW.assigned_to := NEW.assigned_user;\n    END IF;\n  ELSIF TG_OP = 'UPDATE' THEN\n    IF NEW.assigned_to IS DISTINCT FROM OLD.assigned_to THEN\n      NEW.assigned_user := NEW.assigned_to;\n    ELSIF NEW.assigned_user IS DISTINCT FROM OLD.assigned_user THEN\n      NEW.assigned_to := NEW.assigned_user;\n    END IF;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_unified_contacts_validate_tenant","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_unified_contacts_validate_tenant()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_exists boolean;\nBEGIN\n  -- NULL tenant_org_id: reject\n  IF NEW.tenant_org_id IS NULL OR btrim(NEW.tenant_org_id) = '' THEN\n    INSERT INTO public.unified_contacts_insert_violations\n      (violation_type, attempted_tenant_org_id, attempted_lead_id, auth_uid, application_name, client_addr, raw_row)\n    VALUES\n      ('null_tenant', NEW.tenant_org_id, NEW.lead_id, auth.uid(),\n       current_setting('application_name', true),\n       inet_client_addr(),\n       to_jsonb(NEW));\n    RAISE EXCEPTION\n      'unified_contacts.tenant_org_id cannot be NULL (P0.1a-defense). lead_id=%, auth_uid=%',\n      NEW.lead_id, auth.uid()\n      USING ERRCODE = '23514';\n  END IF;\n\n  -- Orphan tenant_org_id: reject\n  SELECT EXISTS (SELECT 1 FROM public.tenants t WHERE t.id::text = NEW.tenant_org_id)\n    INTO v_exists;\n\n  IF NOT v_exists THEN\n    INSERT INTO public.unified_contacts_insert_violations\n      (violation_type, attempted_tenant_org_id, attempted_lead_id, auth_uid, application_name, client_addr, raw_row)\n    VALUES\n      ('orphan_tenant', NEW.tenant_org_id, NEW.lead_id, auth.uid(),\n       current_setting('application_name', true),\n       inet_client_addr(),\n       to_jsonb(NEW));\n    RAISE EXCEPTION\n      'unified_contacts.tenant_org_id=% does not reference an existing tenant (P0.1a-defense). lead_id=%, auth_uid=%',\n      NEW.tenant_org_id, NEW.lead_id, auth.uid()\n      USING ERRCODE = '23514';\n  END IF;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_workflow_template_set_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_workflow_template_set_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"tg_wtv_immutable_when_published","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.tg_wtv_immutable_when_published()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF OLD.status = 'published' AND NEW.status = 'published' THEN\n    IF NEW.cards IS DISTINCT FROM OLD.cards\n       OR NEW.metadata IS DISTINCT FROM OLD.metadata\n       OR NEW.version_number IS DISTINCT FROM OLD.version_number\n       OR NEW.template_id IS DISTINCT FROM OLD.template_id\n       OR NEW.lint_report IS DISTINCT FROM OLD.lint_report\n       OR NEW.rollback_parent_version_id IS DISTINCT FROM OLD.rollback_parent_version_id\n       OR NEW.published_at IS DISTINCT FROM OLD.published_at\n       OR NEW.published_by IS DISTINCT FROM OLD.published_by THEN\n      RAISE EXCEPTION 'Published workflow template versions are immutable. Create a new version instead.';\n    END IF;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"to_business_time","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.to_business_time(value timestamp with time zone)\n RETURNS timestamp without time zone\n LANGUAGE sql\n STABLE\n SET search_path TO 'pg_catalog', 'public'\nRETURN (value AT TIME ZONE business_timezone())\n","identity_arguments":"value timestamp with time zone"},{"name":"to_business_time_label","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.to_business_time_label(value timestamp with time zone)\n RETURNS text\n LANGUAGE sql\n STABLE\n SET search_path TO 'pg_catalog', 'public'\nRETURN (to_char((value AT TIME ZONE business_timezone()), 'YYYY-MM-DD HH12:MI:SS AM'::text) || ' ET'::text)\n","identity_arguments":"value timestamp with time zone"},{"name":"touch_appointment_settings_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_appointment_settings_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN NEW.updated_at = now(); RETURN NEW; END $function$\n","identity_arguments":""},{"name":"touch_cafe_menu_item_media_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_cafe_menu_item_media_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'pg_catalog', 'public'\nAS $function$\nbegin\n  new.updated_at = now();\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"touch_call_summaries_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_call_summaries_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"touch_compliance_settings_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_compliance_settings_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $function$\n","identity_arguments":""},{"name":"touch_elevated_patch_requests","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_elevated_patch_requests()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"touch_lawn_care_readiness_items_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_lawn_care_readiness_items_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'pg_catalog', 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"touch_lawn_service_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_lawn_service_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'pg_catalog', 'public'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"touch_lead_campaigns_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_lead_campaigns_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN NEW.updated_at = now(); RETURN NEW; END $function$\n","identity_arguments":""},{"name":"touch_opportunity_radar_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_opportunity_radar_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'pg_catalog', 'public'\nAS $function$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $function$\n","identity_arguments":""},{"name":"touch_realtor_transactions_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_realtor_transactions_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at := now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"touch_trial_accounts_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_trial_accounts_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN NEW.updated_at = now(); RETURN NEW; END;\n$function$\n","identity_arguments":""},{"name":"touch_vmpsc_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.touch_vmpsc_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.updated_at := now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"trg_rcoq_tenant_guard","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.trg_rcoq_tenant_guard()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  cp_tenant uuid;\n  c_tenant uuid;\n  p_tenant uuid;\nBEGIN\n  SELECT tenant_id INTO cp_tenant FROM public.realtor_campaign_properties WHERE id = NEW.campaign_property_id;\n  SELECT tenant_id INTO c_tenant FROM public.realtor_campaigns WHERE id = NEW.campaign_id;\n  SELECT tenant_id INTO p_tenant FROM public.realtor_properties WHERE id = NEW.property_id;\n  IF cp_tenant IS NULL OR c_tenant IS NULL OR p_tenant IS NULL THEN\n    RAISE EXCEPTION 'Outreach queue: missing parent record';\n  END IF;\n  IF cp_tenant <> NEW.tenant_id OR c_tenant <> NEW.tenant_id OR p_tenant <> NEW.tenant_id THEN\n    RAISE EXCEPTION 'Outreach queue: cross-tenant link blocked';\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"try_cast_uuid","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.try_cast_uuid(_v text)\n RETURNS uuid\n LANGUAGE plpgsql\n IMMUTABLE\n SET search_path TO 'pg_catalog', 'public'\nAS $function$\nBEGIN\n  IF _v IS NULL OR _v = '' THEN RETURN NULL; END IF;\n  RETURN _v::uuid;\nEXCEPTION WHEN others THEN\n  RETURN NULL;\nEND;\n$function$\n","identity_arguments":"_v text"},{"name":"uce_is_member","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.uce_is_member(_tenant_id text)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\n  SELECT EXISTS (\n    SELECT 1 FROM public.user_tenant_memberships\n    WHERE user_id = auth.uid()\n      AND tenant_id::text = _tenant_id\n      AND status = 'active'\n  );\n$function$\n","identity_arguments":"_tenant_id text"},{"name":"uce_is_owner_or_admin","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.uce_is_owner_or_admin(_tenant_id text)\n RETURNS boolean\n LANGUAGE sql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'auth', 'pg_temp'\nAS $function$\n  SELECT public.is_system_admin(auth.uid()) OR EXISTS (SELECT 1 FROM public.user_tenant_memberships m\n    LEFT JOIN public.user_roles ur ON ur.user_id=m.user_id AND ur.tenant_id=m.tenant_id\n    WHERE m.user_id=auth.uid() AND m.tenant_id::text=_tenant_id AND m.status='active'\n      AND (m.is_owner=true OR ur.role::text IN ('Owner','Tenant Owner','Admin','GodMode')));\n$function$\n","identity_arguments":"_tenant_id text"},{"name":"unified_contacts_autofill_name","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.unified_contacts_autofill_name()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF (NEW.name IS NULL OR TRIM(NEW.name) = '') THEN\n    NEW.name := NULLIF(TRIM(CONCAT_WS(' ', NEW.first_name, NEW.last_name)), '');\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"unlink_job_from_claim","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.unlink_job_from_claim(_job_id uuid)\n RETURNS void\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_tenant      uuid;\n  v_prev_claim  uuid;\n  v_actor_email text;\nBEGIN\n  IF auth.uid() IS NULL THEN RAISE EXCEPTION 'unauthenticated' USING ERRCODE='42501'; END IF;\n\n  SELECT tenant_id, contact_claim_id INTO v_tenant, v_prev_claim\n  FROM public.jobs WHERE id = _job_id;\n\n  IF v_tenant IS NULL THEN RAISE EXCEPTION 'job not found' USING ERRCODE='02000'; END IF;\n\n  IF NOT public._is_manager_or_higher_in_tenant(v_tenant) THEN\n    RAISE EXCEPTION 'forbidden' USING ERRCODE='42501';\n  END IF;\n\n  UPDATE public.jobs SET contact_claim_id = NULL WHERE id = _job_id;\n\n  SELECT email INTO v_actor_email FROM auth.users WHERE id = auth.uid();\n\n  INSERT INTO public.job_activity_log\n    (job_id, tenant_id, activity_type, actor_id, actor_email, description, metadata)\n  VALUES (\n    _job_id,\n    v_tenant,\n    'job_claim_unlink',\n    auth.uid(),\n    v_actor_email,\n    CASE\n      WHEN v_prev_claim IS NULL THEN 'Unlink called on already-unlinked job'\n      ELSE 'Unlinked job from claim'\n    END,\n    jsonb_build_object(\n      'action', 'unlink',\n      'previous_claim_id', v_prev_claim,\n      'new_claim_id', NULL\n    )\n  );\nEND; $function$\n","identity_arguments":"_job_id uuid"},{"name":"update_canvassing_stats","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_canvassing_stats()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  UPDATE canvassing_goals\n  SET \n    completed_doors = completed_doors + 1,\n    completed_appointments = CASE WHEN NEW.result_status = 'appointment_set' \n                             THEN completed_appointments + 1 ELSE completed_appointments END,\n    completed_interested = CASE WHEN NEW.result_status = 'interested' \n                           THEN completed_interested + 1 ELSE completed_interested END,\n    updated_at = NOW()\n  WHERE user_id = NEW.user_id::text AND date = CURRENT_DATE;\n\n  INSERT INTO canvassing_goals (tenant_org_id, user_id, date, completed_doors, completed_appointments, completed_interested)\n  VALUES (\n    NEW.tenant_org_id, \n    NEW.user_id::text,\n    CURRENT_DATE, \n    1,\n    CASE WHEN NEW.result_status = 'appointment_set' THEN 1 ELSE 0 END,\n    CASE WHEN NEW.result_status = 'interested' THEN 1 ELSE 0 END\n  ) ON CONFLICT (user_id, date) DO NOTHING;\n\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_contact_claim_payment_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_contact_claim_payment_status(_claim_id uuid, _new_status claim_payment_lifecycle_v4, _note text DEFAULT NULL::text)\n RETURNS contact_claims\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  _uid uuid := auth.uid();\n  _tenant text;\n  _from public.claim_payment_lifecycle_v4;\n  _row public.contact_claims;\nBEGIN\n  IF _uid IS NULL THEN\n    RAISE EXCEPTION 'unauthenticated' USING ERRCODE = '42501';\n  END IF;\n\n  SELECT cc.tenant_org_id, cc.claim_payment_status\n    INTO _tenant, _from\n  FROM public.contact_claims cc\n  WHERE cc.id = _claim_id;\n\n  IF _tenant IS NULL THEN\n    RAISE EXCEPTION 'claim not found' USING ERRCODE = 'P0002';\n  END IF;\n\n  IF NOT (\n    public.is_system_admin(_uid)\n    OR public.is_manager_or_higher(_uid, _tenant::uuid)\n  ) THEN\n    RAISE EXCEPTION 'forbidden: requires Manager, Admin, Owner, Tenant Owner, or GodMode'\n      USING ERRCODE = '42501';\n  END IF;\n\n  UPDATE public.contact_claims\n     SET claim_payment_status = _new_status,\n         claim_payment_status_updated_at = now(),\n         claim_payment_status_updated_by = _uid,\n         updated_at = now()\n   WHERE id = _claim_id\n   RETURNING * INTO _row;\n\n  INSERT INTO public.claim_payment_status_history\n    (claim_id, tenant_org_id, from_status, to_status, changed_by, note, source)\n  VALUES\n    (_claim_id, _tenant, _from, _new_status, _uid, _note, 'manual');\n\n  RETURN _row;\nEND;\n$function$\n","identity_arguments":"_claim_id uuid, _new_status claim_payment_lifecycle_v4, _note text"},{"name":"update_document_drafts_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_document_drafts_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = NOW();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_door_object_status","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_door_object_status()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  UPDATE door_objects\n  SET \n    current_status = NEW.result_status,\n    last_result_at = NEW.visited_at,\n    last_visited_by = NEW.user_id,\n    updated_at = now()\n  WHERE id = NEW.door_id;\n  \n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_new_roofs_queue_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_new_roofs_queue_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_own_profile","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_own_profile(p_name text DEFAULT NULL::text, p_phone text DEFAULT NULL::text, p_company text DEFAULT NULL::text)\n RETURNS profiles\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n  v_uid uuid := auth.uid();\n  v_row public.profiles;\nBEGIN\n  IF v_uid IS NULL THEN\n    RAISE EXCEPTION 'Not authenticated';\n  END IF;\n\n  UPDATE public.profiles\n  SET\n    name       = COALESCE(p_name, name),\n    phone      = COALESCE(p_phone, phone),\n    company    = COALESCE(p_company, company),\n    updated_at = now()\n  WHERE id = v_uid\n  RETURNING * INTO v_row;\n\n  RETURN v_row;\nEND;\n$function$\n","identity_arguments":"p_name text, p_phone text, p_company text"},{"name":"update_permit_history_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_permit_history_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN \n  NEW.updated_at = now(); \n  RETURN NEW; \nEND;\n$function$\n","identity_arguments":""},{"name":"update_quality_score","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_quality_score()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  NEW.quality_score := calculate_quality_score(NEW.name, NEW.phone, NEW.email, NEW.address, NEW.city, NEW.state, NEW.zip);\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_roof_price_book_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_roof_price_book_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $function$\n","identity_arguments":""},{"name":"update_seminole_parcels_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_seminole_parcels_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $function$\n","identity_arguments":""},{"name":"update_settlement_invoices_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_settlement_invoices_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = NOW();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_system_variable_templates_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_system_variable_templates_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_table_row","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_table_row(p_table_name text, p_row_id uuid, p_row_data jsonb)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO ''\nAS $function$\ndeclare\n  v_set_clause text;\n  v_rows integer;\nbegin\n  perform public.require_platform_operator();\n  if not exists (\n    select 1\n    from pg_catalog.pg_class c\n    join pg_catalog.pg_namespace n on n.oid = c.relnamespace\n    where n.nspname = 'public'\n      and c.relname = p_table_name\n      and c.relkind in ('r', 'p')\n  ) then\n    raise exception 'unknown writable public table' using errcode = '22023';\n  end if;\n\n  select string_agg(format('%I = %L', e.key, e.value), ', ')\n  into v_set_clause\n  from jsonb_each_text(coalesce(p_row_data, '{}'::jsonb) - 'id' - 'created_at') e\n  where exists (\n    select 1\n    from information_schema.columns c\n    where c.table_schema = 'public'\n      and c.table_name = p_table_name\n      and c.column_name = e.key\n      and c.is_generated = 'NEVER'\n  );\n\n  if coalesce(v_set_clause, '') = '' then\n    raise exception 'no writable columns supplied' using errcode = '22023';\n  end if;\n\n  execute format(\n    'update public.%I set %s where id = %L::uuid',\n    p_table_name, v_set_clause, p_row_id\n  );\n  get diagnostics v_rows = row_count;\n\n  return jsonb_build_object(\n    'ok', true,\n    'message', 'Row updated successfully',\n    'rows_updated', v_rows\n  );\nend;\n$function$\n","identity_arguments":"p_table_name text, p_row_id uuid, p_row_data jsonb"},{"name":"update_tarping_invoices_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_tarping_invoices_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = NOW();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_tenant_rebuttals_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_tenant_rebuttals_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_unified_contacts_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_unified_contacts_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_updated_at_column","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_updated_at_column()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = NOW();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_workflow_dialogue_templates_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_workflow_dialogue_templates_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"update_workflow_sessions_updated_at","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.update_workflow_sessions_updated_at()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nBEGIN\n  NEW.updated_at = now();\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"user_can_subscribe_topic","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.user_can_subscribe_topic(_topic text)\n RETURNS boolean\n LANGUAGE plpgsql\n STABLE SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_uid uuid := auth.uid();\n  v_tenant uuid;\n  v_user uuid;\nBEGIN\n  IF v_uid IS NULL THEN\n    RETURN false;\n  END IF;\n\n  -- System admins (GodMode) can subscribe to any channel\n  IF public.is_system_admin(v_uid) THEN\n    RETURN true;\n  END IF;\n\n  -- user:<uuid> — only the user themselves\n  IF _topic LIKE 'user:%' THEN\n    BEGIN\n      v_user := substring(_topic from 6)::uuid;\n      RETURN v_user = v_uid;\n    EXCEPTION WHEN others THEN\n      RETURN false;\n    END;\n  END IF;\n\n  -- tenant:<uuid>(:anything) — must be active member\n  IF _topic LIKE 'tenant:%' THEN\n    BEGIN\n      v_tenant := split_part(substring(_topic from 8), ':', 1)::uuid;\n    EXCEPTION WHEN others THEN\n      RETURN false;\n    END;\n    RETURN EXISTS (\n      SELECT 1 FROM public.user_tenant_memberships\n      WHERE user_id = v_uid\n        AND tenant_id = v_tenant\n        AND status = 'active'\n    );\n  END IF;\n\n  -- Postgres changes channels (postgres_changes via supabase) — keep auth-only\n  -- but warn: business code should migrate to tenant: topics.\n  -- Default DENY for unknown topic shapes.\n  RETURN false;\nEND;\n$function$\n","identity_arguments":"_topic text"},{"name":"user_has_permission","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.user_has_permission(p_user_id uuid, p_permission_key text, p_tenant_id uuid DEFAULT NULL::uuid)\n RETURNS boolean\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nDECLARE\n  v_caller uuid := auth.uid();\n  v_override_granted boolean;\n  v_user_roles text[];\n  v_allowed boolean := false;\nBEGIN\n  IF v_caller IS NULL THEN\n    RAISE EXCEPTION 'authentication required' USING ERRCODE='42501';\n  END IF;\n  IF p_user_id IS NULL OR p_permission_key IS NULL OR btrim(p_permission_key) = '' THEN\n    RAISE EXCEPTION 'user and permission are required' USING ERRCODE='22023';\n  END IF;\n\n  v_allowed := (v_caller = p_user_id) OR public.is_system_admin(v_caller);\n\n  IF NOT v_allowed AND p_tenant_id IS NOT NULL THEN\n    v_allowed := public.is_admin_or_higher(v_caller, p_tenant_id)\n      AND public.is_tenant_member(p_user_id, p_tenant_id);\n  END IF;\n\n  IF NOT v_allowed THEN\n    RAISE EXCEPTION 'permission introspection denied' USING ERRCODE='42501';\n  END IF;\n\n  SELECT granted INTO v_override_granted\n  FROM public.user_permission_overrides\n  WHERE user_id = p_user_id\n    AND permission_key = p_permission_key\n    AND (tenant_id IS NULL OR tenant_id = p_tenant_id)\n    AND (expires_at IS NULL OR expires_at > now())\n  LIMIT 1;\n  IF FOUND THEN RETURN v_override_granted; END IF;\n\n  SELECT array_agg(DISTINCT role::text) INTO v_user_roles\n  FROM public.user_roles\n  WHERE user_id = p_user_id\n    AND (tenant_id IS NULL OR tenant_id = p_tenant_id);\n\n  IF 'GodMode' = ANY(coalesce(v_user_roles, ARRAY[]::text[])) THEN RETURN true; END IF;\n\n  RETURN EXISTS (\n    SELECT 1\n    FROM public.role_permissions rp\n    WHERE rp.permission_key = p_permission_key\n      AND rp.role = ANY(coalesce(v_user_roles, ARRAY[]::text[]))\n      AND (rp.tenant_id IS NULL OR rp.tenant_id = p_tenant_id)\n  );\nEND;\n$function$\n","identity_arguments":"p_user_id uuid, p_permission_key text, p_tenant_id uuid"},{"name":"validate_assigned_to_uuid","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.validate_assigned_to_uuid()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.assigned_to IS NOT NULL\n     AND NEW.assigned_to <> ''\n     AND NEW.assigned_to !~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' THEN\n    RAISE EXCEPTION 'assigned_to must be NULL or a UUID. Got: %', NEW.assigned_to\n      USING HINT = 'Resolve email/username to user id (auth.users.id) before writing.';\n  END IF;\n  IF NEW.assigned_to = '' THEN\n    NEW.assigned_to := NULL;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"validate_voicemail_preset_slot","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.validate_voicemail_preset_slot()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.preset_slot IS NOT NULL THEN\n    IF NEW.preset_slot < 1 OR NEW.preset_slot > 4 THEN\n      RAISE EXCEPTION 'preset_slot must be between 1 and 4';\n    END IF;\n    IF NEW.scope <> 'personal' OR NEW.direction <> 'outbound' THEN\n      RAISE EXCEPTION 'preset_slot only allowed on personal outbound templates';\n    END IF;\n    IF NEW.owner_user_id IS NULL THEN\n      RAISE EXCEPTION 'preset_slot requires owner_user_id';\n    END IF;\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""},{"name":"vehicle_lockout_request_record_guard","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.vehicle_lockout_request_record_guard()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nbegin\n  if tg_op = 'INSERT' then\n    if coalesce(new.status, '') not in ('awaiting_signature', 'agreement_prepared') then\n      new.status := 'requested';\n    end if;\n    new.payment_status := 'unpaid';\n    new.source := 'public_site';\n    new.authorization_at := case when new.status in ('awaiting_signature', 'agreement_prepared') then null else coalesce(new.authorization_at, now()) end;\n    new.technician_notes := null;\n    new.amount_due := null;\n    new.amount_paid := null;\n    new.en_route_at := null;\n    new.on_scene_at := null;\n    new.completed_at := null;\n    new.canceled_at := null;\n    new.service_evidence_storage_path := null;\n    new.service_evidence_filename := null;\n    new.authority_verified := false;\n    new.authority_verification_method := null;\n    new.authority_verified_at := null;\n    new.completion_acknowledged := false;\n    new.completion_acknowledgement_name := null;\n    new.completion_acknowledged_at := null;\n  elsif tg_op = 'UPDATE' then\n    if new.authority_verified = true and old.authority_verified = false then\n      new.authority_verified_at := coalesce(new.authority_verified_at, now());\n    elsif new.authority_verified = false then\n      new.authority_verified_at := null;\n      new.authority_verification_method := null;\n    end if;\n    if new.completion_acknowledged = true and old.completion_acknowledged = false then\n      new.completion_acknowledged_at := coalesce(new.completion_acknowledged_at, now());\n    elsif new.completion_acknowledged = false then\n      new.completion_acknowledged_at := null;\n    end if;\n    if new.status is distinct from old.status then\n      if new.status = 'en_route' then\n        new.en_route_at := coalesce(new.en_route_at, now());\n      elsif new.status = 'on_scene' then\n        new.on_scene_at := coalesce(new.on_scene_at, now());\n      elsif new.status = 'completed' then\n        new.completed_at := coalesce(new.completed_at, now());\n      elsif new.status = 'canceled' then\n        new.canceled_at := coalesce(new.canceled_at, now());\n      end if;\n    end if;\n  end if;\n  new.updated_at := now();\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"vehicle_lockout_sync_customer","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.vehicle_lockout_sync_customer()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\ndeclare\n  v_contact_id uuid;\n  v_phone text;\n  v_email text;\n  v_address text;\nbegin\n  v_phone := nullif(regexp_replace(coalesce(new.phone, ''), '\\D', '', 'g'), '');\n  v_email := nullif(lower(btrim(coalesce(new.email, ''))), '');\n  v_address := nullif(regexp_replace(lower(btrim(coalesce(new.service_location, ''))), '\\s+', ' ', 'g'), '');\n\n  perform pg_advisory_xact_lock(\n    hashtextextended(\n      new.tenant_id::text || ':' || coalesce(v_phone, v_email, lower(btrim(new.phone))),\n      0\n    )\n  );\n\n  select contact.id\n    into v_contact_id\n  from public.unified_contacts contact\n  where contact.tenant_org_id = new.tenant_id::text\n    and (\n      (v_phone is not null and contact.normalized_phone = v_phone)\n      or (v_email is not null and contact.normalized_email = v_email)\n    )\n  order by contact.updated_at desc nulls last, contact.created_at desc\n  limit 1;\n\n  if v_contact_id is null then\n    insert into public.unified_contacts (\n      name, phone, normalized_phone, email, normalized_email,\n      address, normalized_address, city, state,\n      status, contact_status, service_status, jobs_stage,\n      source, tenant_org_id, graduated_at, last_touched_at,\n      contact_role, raw_data\n    ) values (\n      new.customer_name, new.phone, v_phone, new.email, v_email,\n      new.service_location, v_address, new.city, 'FL',\n      'Active', 'Active', new.status, new.status,\n      '321_auto_unlock', new.tenant_id::text, now(), now(),\n      'Customer', jsonb_build_object('vehicle_lockout_request_id', new.id::text)\n    )\n    returning id into v_contact_id;\n  else\n    update public.unified_contacts\n    set name = new.customer_name,\n        phone = new.phone,\n        normalized_phone = v_phone,\n        email = coalesce(new.email, email),\n        normalized_email = coalesce(v_email, normalized_email),\n        address = new.service_location,\n        normalized_address = v_address,\n        city = new.city,\n        state = coalesce(state, 'FL'),\n        status = 'Active',\n        contact_status = 'Active',\n        service_status = new.status,\n        jobs_stage = new.status,\n        source = '321_auto_unlock',\n        graduated_at = coalesce(graduated_at, now()),\n        last_touched_at = now(),\n        contact_role = coalesce(contact_role, 'Customer'),\n        raw_data = coalesce(raw_data, '{}'::jsonb)\n          || jsonb_build_object('vehicle_lockout_request_id', new.id::text),\n        updated_at = now()\n    where id = v_contact_id;\n  end if;\n\n  insert into public.contact_tenant_memberships (\n    contact_id, tenant_id, status, contact_status, service_status,\n    jobs_stage, source, contact_role, last_touched_at, updated_at\n  ) values (\n    v_contact_id, new.tenant_id, 'active', 'Active', new.status,\n    new.status, '321_auto_unlock', 'Customer', now(), now()\n  )\n  on conflict (contact_id, tenant_id) do update\n    set status = 'active',\n        contact_status = 'Active',\n        service_status = excluded.service_status,\n        jobs_stage = excluded.jobs_stage,\n        source = '321_auto_unlock',\n        contact_role = coalesce(public.contact_tenant_memberships.contact_role, 'Customer'),\n        last_touched_at = now(),\n        updated_at = now();\n\n  if tg_op = 'INSERT' then\n    insert into public.consent_ledger (\n      tenant_org_id, contact_id, phone_number, phone_normalized,\n      consent_type, consent_status, source, source_url, capture_text,\n      granted_at, metadata\n    ) values\n    (\n      new.tenant_id::text,\n      v_contact_id,\n      new.phone,\n      v_phone,\n      'lawful_authority_attestation',\n      'granted',\n      '321_auto_unlock_public_intake',\n      '/321-auto-unlock',\n      'I confirm I am the owner, authorized driver, or otherwise have lawful authority to request entry into this vehicle.',\n      new.authorization_at,\n      jsonb_build_object(\n        'vehicle_lockout_request_id', new.id::text,\n        'authorization_name', new.authorization_name,\n        'vehicle_year', new.vehicle_year,\n        'vehicle_make', new.vehicle_make,\n        'vehicle_model', new.vehicle_model,\n        'license_plate', new.license_plate,\n        'proof_filename', new.proof_filename,\n        'proof_storage_path', new.proof_storage_path\n      )\n    ),\n    (\n      new.tenant_id::text,\n      v_contact_id,\n      new.phone,\n      v_phone,\n      'vehicle_entry_authorization',\n      'granted',\n      '321_auto_unlock_public_intake',\n      '/321-auto-unlock',\n      'I authorize 321 Auto Unlock to perform vehicle entry service on the vehicle described above.',\n      new.authorization_at,\n      jsonb_build_object(\n        'vehicle_lockout_request_id', new.id::text,\n        'authorization_name', new.authorization_name,\n        'vehicle_year', new.vehicle_year,\n        'vehicle_make', new.vehicle_make,\n        'vehicle_model', new.vehicle_model,\n        'license_plate', new.license_plate,\n        'proof_filename', new.proof_filename,\n        'proof_storage_path', new.proof_storage_path\n      )\n    );\n  end if;\n\n  return new;\nend;\n$function$\n","identity_arguments":""},{"name":"vista_check_availability","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.vista_check_availability(p_unit_name text, p_check_in date, p_check_out date)\n RETURNS boolean\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\nbegin\n  if p_unit_name not in ('The View', 'The Nest') or p_check_in is null or p_check_out is null or p_check_out <= p_check_in or p_check_in < current_date or (p_check_out - p_check_in) > 90 then return false; end if;\n  return not exists (\n    select 1 from public.short_stay_reservations r\n    where r.tenant_id = '71b397ba-b9ad-496b-914c-985d97dbb12e'::uuid\n      and r.unit_name = p_unit_name\n      and r.status = any (array['confirmed'::text, 'checked_in'::text])\n      and r.check_in < p_check_out and r.check_out > p_check_in\n  );\nend;\n$function$\n","identity_arguments":"p_unit_name text, p_check_in date, p_check_out date"},{"name":"vista_create_reservation","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.vista_create_reservation(p_unit_name text, p_check_in date, p_check_out date, p_guest_count integer, p_guest_name text, p_guest_email text, p_guest_phone text, p_notes text DEFAULT NULL::text, p_website text DEFAULT NULL::text)\n RETURNS jsonb\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public', 'pg_temp'\nAS $function$\ndeclare\n  v_id uuid := gen_random_uuid();\n  v_reference text;\n  v_recent_count integer;\nbegin\n  if coalesce(trim(p_website), '') <> '' then return jsonb_build_object('ok', true, 'status', 'pending', 'reference', 'VDM'); end if;\n  if p_unit_name not in ('The View', 'The Nest') or p_check_in is null or p_check_out is null or p_check_out <= p_check_in or p_check_in < current_date or (p_check_out - p_check_in) > 90 then return jsonb_build_object('ok', false, 'code', 'INVALID_DATES', 'message', 'Choose valid future check-in and check-out dates.'); end if;\n  if p_guest_count is null or p_guest_count < 1 or p_guest_count > 2 then return jsonb_build_object('ok', false, 'code', 'INVALID_GUEST_COUNT', 'message', 'These vacation homes accommodate up to two guests.'); end if;\n  if length(trim(coalesce(p_guest_name, ''))) < 2 or position('@' in trim(coalesce(p_guest_email, ''))) < 2 or length(trim(coalesce(p_guest_phone, ''))) < 7 then return jsonb_build_object('ok', false, 'code', 'CONTACT_REQUIRED', 'message', 'Name, email, and phone are required.'); end if;\n  if not public.vista_check_availability(p_unit_name, p_check_in, p_check_out) then return jsonb_build_object('ok', false, 'code', 'DATES_UNAVAILABLE', 'message', 'Those dates are already reserved.'); end if;\n\n  select count(*) into v_recent_count from public.short_stay_reservations r\n  where r.tenant_id = '71b397ba-b9ad-496b-914c-985d97dbb12e'::uuid\n    and r.source = 'direct_web'\n    and r.created_at >= now() - interval '1 hour'\n    and (lower(coalesce(r.guest_email, '')) = lower(trim(coalesce(p_guest_email, ''))) or coalesce(r.guest_phone, '') = trim(coalesce(p_guest_phone, '')));\n  if v_recent_count >= 5 then return jsonb_build_object('ok', false, 'code', 'TOO_MANY_REQUESTS', 'message', 'We already have several recent reservation requests from this contact. Please contact La Vista del Mar directly if you need help.'); end if;\n\n  v_reference := 'VDM-' || upper(substr(replace(v_id::text, '-', ''), 1, 8));\n  insert into public.short_stay_reservations (id, tenant_id, unit_name, guest_name, guest_email, guest_phone, source, check_in, check_out, status, guest_count, amount_paid, payment_status, notes, metadata)\n  values (v_id, '71b397ba-b9ad-496b-914c-985d97dbb12e'::uuid, p_unit_name, left(trim(p_guest_name),120), left(lower(trim(p_guest_email)),180), left(trim(p_guest_phone),40), 'direct_web', p_check_in, p_check_out, 'inquiry', p_guest_count, 0, 'unpaid', nullif(left(trim(coalesce(p_notes,'')),1200),''), jsonb_build_object('channel','knocklaunch_direct','customer_facing',true,'reference',v_reference));\n  return jsonb_build_object('ok', true, 'status', 'pending', 'reference', v_reference);\nend;\n$function$\n","identity_arguments":"p_unit_name text, p_check_in date, p_check_out date, p_guest_count integer, p_guest_name text, p_guest_email text, p_guest_phone text, p_notes text, p_website text"},{"name":"visual_witness_expired_storage_paths","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.visual_witness_expired_storage_paths(p_before timestamp with time zone, p_limit integer DEFAULT 500)\n RETURNS TABLE(name text)\n LANGUAGE sql\n SECURITY DEFINER\n SET search_path TO 'pg_catalog', 'public'\nAS $function$\n  SELECT object.name\n  FROM storage.objects AS object\n  WHERE object.bucket_id = 'command-center-visual-witness'\n    AND object.created_at < COALESCE(p_before, now() - interval '14 days')\n    AND (\n      object.name LIKE 'universal-witness/%'\n      OR object.name LIKE 'hosted-runner/%'\n      OR object.name LIKE 'tenant/%'\n      OR object.name LIKE 'visual-witness-jobs/%'\n    )\n  ORDER BY object.created_at ASC, object.name ASC\n  LIMIT LEAST(GREATEST(COALESCE(p_limit, 500), 1), 1000);\n$function$\n","identity_arguments":"p_before timestamp with time zone, p_limit integer"},{"name":"voicemail_dtmf_tokens_validate","schema":"public","definition":"CREATE OR REPLACE FUNCTION public.voicemail_dtmf_tokens_validate()\n RETURNS trigger\n LANGUAGE plpgsql\n SET search_path TO 'public'\nAS $function$\nBEGIN\n  IF NEW.expires_at > now() + interval '15 minutes' THEN\n    RAISE EXCEPTION 'voicemail_dtmf_tokens.expires_at exceeds 15-minute ceiling';\n  END IF;\n  IF NEW.expires_at <= now() THEN\n    RAISE EXCEPTION 'voicemail_dtmf_tokens.expires_at must be in the future';\n  END IF;\n  RETURN NEW;\nEND;\n$function$\n","identity_arguments":""}],"cron_jobs":[{"active":true,"command":"select private.expire_stale_user_sessions(interval '60 minutes');","jobname":"knocklaunch-expire-stale-user-sessions","schedule":"*/15 * * * *"},{"active":true,"command":"select private.prune_call_lifecycle_debug_events(interval '7 days');","jobname":"knocklaunch-prune-call-lifecycle-debug-events","schedule":"17 3 * * *"},{"active":true,"command":"select private.system_backup_edge_request('start','weekly',null,false);","jobname":"knocklaunch-weekly-full-backup","schedule":"15 8 * * 0"},{"active":true,"command":"select private.system_backup_edge_request('resume','recovery-pulse',null,false);","jobname":"knocklaunch-backup-recovery-pulse","schedule":"*/15 * * * *"}],"extensions":[{"name":"btree_gist","version":"1.7"},{"name":"cube","version":"1.5"},{"name":"earthdistance","version":"1.2"},{"name":"fuzzystrmatch","version":"1.2"},{"name":"pg_cron","version":"1.6.4"},{"name":"pg_net","version":"0.20.3"},{"name":"pg_stat_statements","version":"1.11"},{"name":"pg_trgm","version":"1.6"},{"name":"pgcrypto","version":"1.3"},{"name":"pgmq","version":"1.5.1"},{"name":"plpgsql","version":"1.0"},{"name":"supabase_vault","version":"0.3.1"},{"name":"uuid-ossp","version":"1.1"}],"captured_at":"2026-09-03T19:47:39.878616+00:00","server_version":"17.6","migration_history":[{"name":"af1291c7-72ba-4090-aabe-cfb61a190943","version":"20251206122717"},{"name":"3c431b73-2989-4914-ac21-7285fb479ca1","version":"20251206122746"},{"name":"742dd6c3-db15-46cc-a746-8c42a354f3d0","version":"20251206123638"},{"name":"5bae2680-ec2d-4313-a670-7f61dfd2a403","version":"20251206123658"},{"name":"7acd1d16-f02a-41d1-8ace-7fdca63409a1","version":"20251206123740"},{"name":"26ccb3a7-481f-4146-a7f5-80b9fa5a3f6c","version":"20251206131116"},{"name":"4fd25a26-3c50-4c43-acfb-7c4051534992","version":"20251206131205"},{"name":"b796abec-5644-4f97-b8a5-d6a93c56ecac","version":"20251206134521"},{"name":"9a1422ec-747a-44a4-a730-61bc58966b31","version":"20251206214338"},{"name":"encore_canonical_claim_stage","version":"20260812144215"},{"name":"harden_customer_portal_token_contract","version":"20260812195936"},{"name":"revoke_portal_when_claims_close","version":"20260812200236"},{"name":"harden_privileged_backend_boundaries","version":"20260812203000"},{"name":"harden_internal_rpc_execution","version":"20260812205500"},{"name":"reconcile_canonical_migration_ledger","version":"20260812212048"},{"name":"harden_trigger_function_execute_privileges","version":"20260813050000"},{"name":"harden_all_trigger_function_execute_privileges","version":"20260813054500"},{"name":"create_pa_staff_compliance","version":"20260813071000"},{"name":"create_pa_staff_compliance","version":"20260813071103"},{"name":"add_pa_claim_automation_pack","version":"20260813072226"},{"name":"add_pa_claim_automation_pack","version":"20260813073000"},{"name":"harden_remaining_function_search_paths","version":"20260813074000"},{"name":"create_pa_carrier_estimate_items","version":"20260813084500"},{"name":"create_pa_carrier_estimate_items","version":"20260813100747"},{"name":"claim_scope_customer_portal_access","version":"20260813113000"},{"name":"shared_claim_valuation_scope","version":"20260813113500"},{"name":"harden_internal_auth_helper_rpc_grants","version":"20260813115000"},{"name":"harden_ai_auth_helper_anon_grants","version":"20260813115500"},{"name":"fix_claim_stage_dispatch_contact_scope","version":"20260813125535"},{"name":"repair_academy_membership_onboarding_contract","version":"20260814173727"},{"name":"unify_onboarding_provisioning_contract","version":"20260814200148"},{"name":"reconcile_default_roles_with_explicit_assignments","version":"20260814200223"},{"name":"fix_academy_global_course_nested_access","version":"20260814200333"},{"name":"harden_onboarding_academy_and_license_research","version":"20260814205121"},{"name":"make_onboarding_research_idempotent","version":"20260814205259"},{"name":"secure_onboarding_and_make_academy_role_aware","version":"20260814210255"},{"name":"add_owner_safe_self_service_onboarding_orchestrator","version":"20260814210403"},{"name":"lock_raw_academy_enrollment_and_add_safe_retry","version":"20260814210431"},{"name":"align_canonical_tenant_types_with_tenant_contract","version":"20260814210511"},{"name":"repair_tenant_provisioning_logo_contract","version":"20260814210556"},{"name":"stop_writing_through_tenant_organizations_view","version":"20260814210634"},{"name":"add_automatic_onboarding_license_research_dispatch","version":"20260814212546"},{"name":"align_onboarding_session_state_machine","version":"20260814212651"},{"name":"separate_owner_research_and_scope_vertical_academy","version":"20260814213114"},{"name":"make_async_research_preserve_provisioned_onboarding_state","version":"20260814213154"},{"name":"adaptive_command_center_tenant_resolution","version":"20260815134500"},{"name":"mobile_vendor_event_constraint_prerequisites","version":"20260815204459"},{"name":"mobile_vendor_event_operating_system","version":"20260815204500"},{"name":"reconcile_mobile_vendor_event_operating_system","version":"20260815215000"},{"name":"create_communication_setup_requests","version":"20260816035000"},{"name":"live_edit_tenant_override_rls","version":"20260816105000"},{"name":"live_edit_v2_history_templates","version":"20260816151000"},{"name":"phone_first_auth_identity","version":"20260816170000"},{"name":"finance_recordkeeping","version":"20260816172100"},{"name":"finance_report_automation","version":"20260816224500"},{"name":"create_thirsty_panda_tenant","version":"20260817044500"},{"name":"thirsty_panda_cafe_qsr","version":"20260817143000"},{"name":"thirsty_panda_owner_office_operations","version":"20260817190000"},{"name":"thirsty_panda_full_menu_media_library","version":"20260817224500"},{"name":"cafe_qsr_tenant_type_contract","version":"20260818124500"},{"name":"knocklaunch_mail360_platform","version":"20260818133600"},{"name":"add_auto_detailing_vertical_and_tranzformer_tenant","version":"20260818144500"},{"name":"reconcile_knocklaunch_mail360_platform","version":"20260818184300"},{"name":"remove_customer_tenant_as_command_center_platform_anchor","version":"20260818233526"},{"name":"fix_command_center_platform_mission_anchor","version":"20260818233700"},{"name":"add_square_tenant_payments","version":"20260819000500"},{"name":"fix_explicit_tenant_member_godmode","version":"20260819042147"},{"name":"align_platform_admin_tenant_manager_authority","version":"20260819043300"},{"name":"restore_cached_parcel_intel_view_fields","version":"20260819073900"},{"name":"zoho_mail_direct_provider","version":"20260819143500"},{"name":"add_zoho_mail_platform_vault_reader","version":"20260819165700"},{"name":"deterministic_business_operations_core","version":"20260819203500"},{"name":"platform_zoho_mail_credentials","version":"20260820015500"},{"name":"supabase_auth_security_repair","version":"20260820214500"},{"name":"optimize_supabase_hot_paths","version":"20260820220000"},{"name":"harden_public_security_definer_rpc_surface","version":"20260820222500"},{"name":"optimize_supabase_policy_topology","version":"20260820223000"},{"name":"optimize_command_center_mission_resolution","version":"20260820223500"},{"name":"close_remaining_authz_bypasses","version":"20260820224500"},{"name":"optimize_session_telemetry_integrity","version":"20260820231000"},{"name":"optimize_unified_contacts_read_paths","version":"20260820232000"},{"name":"retire_call_lifecycle_debug_noise","version":"20260820233000"},{"name":"mobile_vendor_growth_club","version":"20260821175400"},{"name":"big_papis_loyalty_member_portal","version":"20260822021500"},{"name":"big_papis_referral_points","version":"20260822175500"},{"name":"make_finance_transaction_sources_provider_agnostic","version":"20260824153500"},{"name":"mobile_vendor_schedule_import_recovery","version":"20260824172500"},{"name":"harden_big_papis_loyalty_integrity","version":"20260825014800"},{"name":"mobile_vendor_loyalty_cash_purchases","version":"20260825031000"},{"name":"tenant_ad_analytics_events","version":"20260825032500"},{"name":"mobile_vendor_inventory_ledger","version":"20260825061000"},{"name":"mobile_vendor_event_finance_and_domain_truth","version":"20260825062000"},{"name":"owner_workspace_notes_and_deterministic_tasks","version":"20260826214500"},{"name":"tenant_photo_studio","version":"20260827223000"},{"name":"vista_short_term_rental","version":"20260827232500"},{"name":"vista_first_party_reservations","version":"20260828184000"},{"name":"fix_mobile_vendor_inventory_adjustment","version":"20260829022000"},{"name":"add_unified_inbox_contact_fk","version":"20260829023500"},{"name":"add_jobs_funding_type","version":"20260829121500"},{"name":"add_job_financing_overlay","version":"20260829123500"},{"name":"redfish_contact_first_spine","version":"20260829124200"},{"name":"knocklaunch_demo_requests","version":"20260829134500"},{"name":"roof_help_funnel_events","version":"20260829144500"},{"name":"align_backend_tenant_type_canonicalization","version":"20260830140500"},{"name":"tenant_media_library","version":"20260830142554"},{"name":"tenant_media_library_existing_media_backfill","version":"20260830151500"},{"name":"enforce_strict_tenant_type_contract","version":"20260830152000"},{"name":"media_taxonomy_v1","version":"20260830164000"},{"name":"demo_request_completion_workflow","version":"20260830214000"},{"name":"roofing_operating_system","version":"20260831041000"},{"name":"roofing_portal_projection","version":"20260831045500"},{"name":"roofing_portal_canonical_tokens","version":"20260831050000"},{"name":"tenant_owned_storage_buckets","version":"20260831131500"},{"name":"redfish_roofing_contract_repairs","version":"20260831222417"},{"name":"redfish_owner_demo_completion","version":"20260831222418"},{"name":"redfish_roofhelpfinder_jimmy_routing","version":"20260831235000"},{"name":"create_vehicle_lockout_requests","version":"20260901014812"},{"name":"progress_platform_records","version":"20260901023000"},{"name":"321_auto_unlock_service_record","version":"20260901031500"},{"name":"redfish_demo_financial_readiness","version":"20260901105500"},{"name":"enable_redfish_storm_report","version":"20260901110500"},{"name":"public_321_auto_unlock_brand","version":"20260901110800"},{"name":"normalize_tenant_logo_ingest_base64","version":"20260901130500"},{"name":"expand_live_edit_operations","version":"20260901140000"},{"name":"fix_roofing_ops_platform_admin_access","version":"20260901183000"},{"name":"open_exact_media_reorg_upload_targets","version":"20260901184201"},{"name":"open_exact_media_reorg_copy_sources","version":"20260901184303"},{"name":"enable_http_for_bounded_media_reorg","version":"20260901184421"},{"name":"normalize_redfish_demo_contact_ids","version":"20260901184500"},{"name":"allow_clean_big_papis_video_reorg_target","version":"20260901184829"},{"name":"close_tenant_media_reorg_window","version":"20260901190322"},{"name":"temp_generated_media_legacy_delete_scope","version":"20260901193627"},{"name":"remove_temp_generated_media_legacy_delete_scope","version":"20260901193740"},{"name":"canonicalize_tenant_media_storage","version":"20260901195800"},{"name":"temporary_exact_legacy_media_delete_scope_20260901","version":"20260901200714"},{"name":"remove_temporary_exact_legacy_media_delete_scope_20260901","version":"20260901200814"},{"name":"retire_legacy_tenant_storage_contract","version":"20260901202000"},{"name":"standardize_tenant_media_branding","version":"20260901203500"},{"name":"seed_unambiguous_tenant_branding_logos","version":"20260901205500"},{"name":"321_auto_unlock_esign_intake","version":"20260901213000"},{"name":"public_321_auto_unlock_video_branding","version":"20260901220500"},{"name":"allow_multiple_roof_estimates_per_contact","version":"20260901225000"},{"name":"expand_tenant_provider_connections","version":"20260902033500"},{"name":"preserve_321_pre_submit_status","version":"20260902040000"},{"name":"redfish_tenant_specific_rebuttals","version":"20260902053000"},{"name":"tenant_content_isolation_contract","version":"20260902054500"},{"name":"restore_default_stormscore_model","version":"20260902132500"},{"name":"create_user_tenant_tutorial_state","version":"20260902161000"},{"name":"create_user_tenant_tutorial_progress","version":"20260902164500"},{"name":"atomic_big_papis_proposal_numbers","version":"20260902182000"},{"name":"redfish_scope_agreement_resolver","version":"20260902183500"},{"name":"roof_measurement_jobs","version":"20260902192500"},{"name":"fix_vehicle_lockout_pre_submit_status_check","version":"20260903011500"},{"name":"prehistoric_001_deterministic_tenant_media","version":"20260903020000"},{"name":"harden_prehistoric_001_tenant_media","version":"20260903021500"},{"name":"platform_security_hardening_10_10","version":"20260903023500"},{"name":"prehistoric_002_universal_proposals","version":"20260903024500"},{"name":"security_rpc_least_privilege","version":"20260903024600"},{"name":"job_readiness_tenant_guard","version":"20260903024900"},{"name":"guard_user_permission_introspection","version":"20260903025300"},{"name":"harden_prehistoric_002_verified_renders","version":"20260903030000"},{"name":"security_final_10_of_10","version":"20260903033000"},{"name":"security_metadata_boundaries_10_of_10","version":"20260903035000"},{"name":"security_tenant_policy_boundaries_10_of_10","version":"20260903041000"},{"name":"security_authorization_primitives_10_of_10","version":"20260903042000"},{"name":"security_role_scope_invariant_10_of_10","version":"20260903043000"},{"name":"security_dnc_notification_scope_10_of_10","version":"20260903044000"},{"name":"security_active_membership_authorization_10_of_10","version":"20260903045000"},{"name":"security_membership_role_promotion_10_of_10","version":"20260903046000"},{"name":"security_public_upload_contract_10_of_10","version":"20260903047000"},{"name":"pcg_card_vault","version":"20260903133000"},{"name":"pcg_card_grading_core_v2","version":"20260903140839"},{"name":"pcg_operator_v2","version":"20260903142500"},{"name":"weekly_full_backup_system","version":"20260903165000"},{"name":"allow_one_time_pcg_workspace_background_seed","version":"20260903173741"},{"name":"remove_one_time_pcg_workspace_background_seed","version":"20260903173759"},{"name":"system_backup_r2_identity","version":"20260903181000"},{"name":"pcg_demo_growth_support_and_inventory_tier","version":"20260903191708"},{"name":"pcg_demo_growth_support_and_inventory_tier","version":"20260903192500"},{"name":"system_backup_catalog_timeout","version":"20260903194704"}],"vault_secret_names":[{"name":"Client Secret","description":""},{"name":"knocklaunch_platform_zoho_mail_client_id","description":""},{"name":"knocklaunch_platform_zoho_mail_client_secret","description":""},{"name":"knocklaunch_system_backup_trigger","description":"Machine-only token used by pg_cron/pg_net to invoke the KNOCKLAUNCH system-backup Edge Function."},{"name":"knocklaunch_zoho_mail_client_id","description":"Knocklaunch Zoho Mail "},{"name":"knocklaunch_zoho_mail_client_secret","description":"knocklaunch zoho mail "}]}