{
  "schemaVersion": 1,
  "generatedAt": "2026-08-21T23:38:34.355Z",
  "language": "es-AR",
  "title": "Supabase public schema para HCD Chivilcoy",
  "status": {
    "projectName": "Chivilcoy",
    "projectRef": "nqftlaviydpsqbbdvthr",
    "schemaApplied": true,
    "bulkImportsPrepared": true,
    "bulkImportsLoaded": true,
    "productionProxyConfigured": true,
    "primarySqlReadActiveForBulletinSearch": true,
    "bulletinSearchSqlFiltersActive": true,
    "primarySqlReadActiveForProcurementSuppliers": true,
    "primarySqlReadActiveForPublicFinance": true,
    "fallbackJsonActive": true,
    "primarySqlReadActiveForPublicLegislative": true,
    "primarySqlReadActiveForAiSearch": true,
    "productionProxyCacheActive": true,
    "publicSiteApiSyncPrepared": true,
    "publicSnapshotSourceDiagnosticActive": true,
    "legislativeAdminSchemaApplied": true,
    "legislativeAdminBootstrapLoaded": true,
    "legislativeAdminAnonAccessDisabled": true,
    "legislativeAdminRuntimeMirrorPrepared": true,
    "aiSearchRefreshRpcApplied": true
  },
  "runtime": {
    "statusEndpoint": "/api/index.php?action=supabase_status",
    "searchEndpoint": "/api/index.php?action=bulletin_search",
    "procurementEndpoint": "/api/index.php?action=procurement_suppliers",
    "financeEndpoint": "/api/index.php?action=public_finance",
    "primaryReadStrategy": "Usar el proxy PHP para consultas públicas paginadas cuando esté configurado; conservar JSON como fallback operativo.",
    "statusEndpointGuarantee": "No expone claves. Devuelve configuración, disponibilidad REST, conteos por vista pública y siguiente paso operacional.",
    "aiSearchEndpoint": "/api/index.php?action=public_search&q=consulta",
    "publicProxyCache": {
      "location": "api/.cache/supabase-public",
      "serverSideOnly": true,
      "staleIfError": true,
      "survivesDeploy": true,
      "cachedActions": [
        "bulletin_search",
        "procurement_suppliers",
        "public_finance",
        "public_search"
      ]
    },
    "publicSiteSync": {
      "applySqlCommand": "npm run supabase:apply-sql -- tmp/reports/public-site-api-supabase-import.sql",
      "applySyncCommand": "npm run site:sync:supabase -- --apply",
      "exportSqlCommand": "npm run site:sql:supabase:api",
      "mysqlSourceAction": "/api/index.php?action=public_snapshot",
      "purgeCacheCommand": "npm run hostinger:purge-cache",
      "safeDryRunCommand": "npm run site:sync:supabase",
      "statusField": "/api/index.php?action=supabase_status -> data.publicSnapshotSource y data.syncSources",
      "strictMysqlSyncCommand": "npm run site:sync:supabase -- --apply --source public_snapshot --strict-source"
    },
    "legislativeAdminMigration": {
      "migrationSql": "docs/migrations/2026-06-27-legislative-admin-supabase.sql",
      "exportSqlCommand": "npm run legislative-admin:sql:supabase",
      "latestImportSql": "tmp/reports/legislative-admin-supabase-import.sql",
      "targetTables": [],
      "securityModel": "RLS activo en todas las tablas; anon sin SELECT/INSERT/UPDATE/DELETE; authenticated solo SELECT con perfil activo; escrituras publicas deshabilitadas.",
      "nextWriteStep": "Conectar el panel administrativo server-side a estas tablas o agregar policies de escritura finas despues de migrar usuarios a Supabase Auth."
    }
  },
  "readinessGate": {
    "script": "npm run supabase:readiness",
    "strictScript": "npm run supabase:readiness -- --strict",
    "requiredBeforePrimarySqlRead": true,
    "readyWhen": "Todas las tablas y vistas publicas responden por Data API y los conteos coinciden con importArtifacts.",
    "currentKnownState": "Las tablas estan creadas, la carga masiva fue importada y el proxy PHP de Hostinger esta configurado para lecturas Supabase REST. La busqueda textual de boletines, proveedores, transparencia presupuestaria, tasas, snapshot legislativo publico y busqueda IA full-text usan Supabase como lectura primaria; el proxy mantiene cache server-side stale-if-error y la web conserva JSON/seeds como respaldo.",
    "lastDatabaseCheck": {
      "checkedAt": "2026-06-27T20:47:57Z",
      "readiness": "ready",
      "method": "Supabase MCP execute_sql + advisors",
      "tablesWithExpectedCounts": 12,
      "checkedTables": 12,
      "checkedViews": 12,
      "viewRows": {
        "ai_public_corpus": 30527,
        "ai_public_search_documents": 30527,
        "official_bulletin_search_index": 29322,
        "procurement_supplier_line_reviews": 2695,
        "procurement_supplier_records": 2695,
        "procurement_supplier_summary": 358,
        "public_document_index": 181
      },
      "legislativeAdmin": {
        "checkedAt": "2026-06-27T22:12:37Z",
        "method": "Supabase MCP execute_sql + advisors",
        "securityAdvisors": "sin lints",
        "performanceAdvisors": "solo unused_index INFO; esperable en tablas recien creadas y no se removieron indices preventivos.",
        "rowCounts": {
          "blocks": 7,
          "councilors": 26,
          "documents": 0,
          "news": 3,
          "projectAuthors": 8,
          "projectTags": 8,
          "projectVotes": 104,
          "projects": 4,
          "sessionAttendance": 0,
          "sessions": 3,
          "staff": 6
        }
      },
      "aiSearchRefreshRpc": {
        "checkedAt": "2026-06-27T22:12:37Z",
        "function": "refresh_ai_public_search_documents",
        "migrationSql": "docs/migrations/2026-06-27-ai-search-refresh-rpc.sql",
        "executeGrants": [],
        "anonExecute": false,
        "authenticatedExecute": false,
        "lastVerifiedRows": 30527,
        "securityAdvisors": "sin lints"
      }
    },
    "lastProductionApiCheck": {
      "checkedAt": "2026-06-27T22:00:10Z",
      "endpoint": "/api/index.php?action=supabase_status",
      "readiness": "ready",
      "configured": true,
      "method": "Hostinger PHP proxy -> Supabase REST",
      "publicProxyCache": {
        "observed": true,
        "sample": "public_search Lucas Burgos: miss -> hit; 2627 ms -> 111 ms",
        "writable": true
      },
      "publicSnapshotSource": {
        "configured": false,
        "configFileExists": true,
        "pdoMysqlLoaded": true,
        "reachable": false,
        "missingKeys": [],
        "observedAt": "2026-06-27T21:29:33Z"
      },
      "viewRows": {
        "accountability_metrics": 965,
        "accountability_reports": 1,
        "ai_public_corpus": 30527,
        "ai_public_search_documents": 30527,
        "municipal_tax_rows": 17,
        "official_bulletin_search_index": 29322,
        "procurement_supplier_line_reviews": 2695,
        "procurement_supplier_records": 2695,
        "procurement_supplier_summary": 358,
        "public_document_index": 181
      },
      "legislativeAdmin": {
        "checkedAt": "2026-06-27T22:01:52Z",
        "method": "Supabase MCP execute_sql + advisors",
        "securityAdvisors": "sin lints",
        "performanceAdvisors": "solo unused_index INFO; esperable en tablas recien creadas y no se removieron indices preventivos.",
        "rowCounts": {
          "blocks": 7,
          "councilors": 26,
          "documents": 0,
          "news": 3,
          "projectAuthors": 8,
          "projectTags": 8,
          "projectVotes": 104,
          "projects": 4,
          "sessionAttendance": 0,
          "sessions": 3,
          "staff": 6
        }
      }
    },
    "lastSupabaseAdvisorCheck": {
      "checkedAt": "2026-06-27T22:01:52Z",
      "performance": "solo unused_index INFO en indices existentes y nuevos; no se removieron hasta medir uso real. EXPLAIN de busqueda selectiva usa Bitmap Index Scan sobre ai_public_search_documents_vector_idx",
      "security": "sin lints"
    }
  },
  "notes": [
    "Las tablas publicas tienen RLS activo y policies de SELECT para anon/authenticated.",
    "No hay policies de escritura publica; las cargas se hacen por SQL controlado o usuario de base.",
    "Los PDFs e imagenes permanecen como archivos; Postgres guarda texto, metadata y trazabilidad.",
    "La web conserva JSON publicos como fallback mientras se activa la lectura Supabase por pantalla.",
    "El proxy PHP guarda cache server-side de lecturas publicas en api/.cache/supabase-public; no cachea datos administrativos ni claves.",
    "bulletin_search acepta category y quality para resolver filtros frecuentes desde SQL/cache sin descargar historicos-index.json, wordpress-index.json ni sibom-index.json.",
    "Para sincronizar cambios legislativos hacia Supabase, usar npm run site:sync:supabase como dry-run seguro y npm run site:sync:supabase -- --apply para exportar, aplicar SQL, chequear readiness y purgar cache publico.",
    "supabase_status publica data.publicSnapshotSource para diagnosticar si MySQL puede alimentar public_snapshot sin exponer host, usuario, base ni contrasena."
  ],
  "recommendedViewsForAgents": [
    {
      "view": "official_bulletin_search_index",
      "purpose": "Buscar bloques de boletines por texto, año, tipo, categoría derivada, calidad de texto, tema y ruta de lector.",
      "keyFields": [
        "block_key",
        "bulletin_id",
        "block_id",
        "bulletin_title",
        "year",
        "label",
        "title",
        "text_category",
        "quality_status",
        "body_preview",
        "body_search",
        "route",
        "pdf_url"
      ]
    },
    {
      "view": "procurement_supplier_summary",
      "purpose": "Ranking y resumen de proveedores con cantidad de líneas, montos y faltantes.",
      "keyFields": [
        "supplier_key",
        "supplier_name",
        "line_count",
        "amount_count",
        "missing_amount_count",
        "amount_total",
        "years"
      ]
    },
    {
      "view": "procurement_supplier_records",
      "purpose": "Vista unificada para renderizar proveedores sin descargar boletines completos: línea proveedor, acto, boletín, fecha, método, monto, fuente y enlace interno.",
      "keyFields": [
        "supplier_line_key",
        "supplier_key",
        "supplier_name",
        "act_label",
        "act_date",
        "contract_type",
        "amount",
        "amount_label",
        "bulletin_id",
        "block_id",
        "internal_url",
        "source_url"
      ]
    },
    {
      "view": "procurement_supplier_line_reviews",
      "purpose": "Líneas proveedor auditadas con fuente, revisión, monto y estado.",
      "keyFields": [
        "supplier_line_key",
        "review_key",
        "supplier_name",
        "amount",
        "amount_label",
        "source_url",
        "source_page",
        "status"
      ]
    },
    {
      "view": "accountability_reports",
      "purpose": "Rendiciones anuales con cifras base, ruta pública, periodo, fuente y documentos asociados.",
      "keyFields": [
        "report_year",
        "title",
        "route",
        "source_file",
        "period_label",
        "published_label",
        "figures",
        "source"
      ]
    },
    {
      "view": "accountability_metrics",
      "purpose": "Series y métricas presupuestarias normalizadas para transparencia: ingresos, gastos, deuda, modificaciones, metas y patrimonio.",
      "keyFields": [
        "report_year",
        "metric_group",
        "metric_key",
        "label",
        "amount",
        "note",
        "metadata"
      ]
    },
    {
      "view": "municipal_tax_rows",
      "purpose": "Rubros RAFAM 12.1 auditados con clasificación legal, monto, referencias normativas y trazabilidad.",
      "keyFields": [
        "tax_year",
        "code",
        "label",
        "legal_kind",
        "amount",
        "fiscal_reference",
        "impositive_reference",
        "traceability_note"
      ]
    },
    {
      "view": "ai_public_corpus",
      "purpose": "Corpus unificado para agentes IA: boletines, tasas, métricas de rendición, documentos y datos legislativos del sitio.",
      "keyFields": [
        "entity_type",
        "entity_id",
        "title",
        "summary",
        "body",
        "route",
        "source_url",
        "year",
        "tags",
        "metadata"
      ]
    },
    {
      "view": "ai_public_search_documents",
      "purpose": "Tabla cacheada con tsvector e índice GIN para búsqueda full-text pública. Usar preferentemente vía /api/index.php?action=public_search&q=consulta.",
      "keyFields": [
        "entity_type",
        "entity_id",
        "title",
        "summary",
        "route",
        "source_url",
        "year",
        "tags",
        "metadata"
      ]
    },
    {
      "view": "public_document_index",
      "purpose": "Inventario de PDFs y documentos públicos con owner y URL.",
      "keyFields": [
        "document_id",
        "owner_type",
        "owner_id",
        "title",
        "category",
        "url",
        "mime_type"
      ]
    },
    {
      "purpose": "Snapshot compacto para renderizar inicio, sesiones, proyectos, votaciones, concejales, bloques y noticias desde Supabase sin depender de MySQL.",
      "keyFields": [
        "snapshot_key",
        "generated_at",
        "councilors",
        "sessions",
        "projects",
        "news",
        "staff",
        "metadata"
      ]
    },
    {
      "purpose": "Indice para agentes IA sobre datos legislativos publicos: concejales, sesiones, proyectos, noticias y staff.",
      "keyFields": [
        "entity_type",
        "entity_id",
        "title",
        "summary",
        "body",
        "route",
        "year",
        "tags",
        "metadata"
      ]
    }
  ],
  "tables": [
    "official_bulletin_index",
    "official_bulletin_text_blocks",
    "public_documents",
    "accountability_reports",
    "accountability_metrics",
    "municipal_tax_rows",
    "ai_data_resources",
    "procurement_bulletins",
    "procurement_acts",
    "procurement_suppliers",
    "procurement_supplier_lines",
    "ai_public_search_documents"
  ],
  "restrictedTables": [],
  "importArtifacts": [
    {
      "path": "tmp/reports/public-content-supabase-import.sql",
      "rows": {
        "accountabilityMetrics": 965,
        "aiResources": 53,
        "bulletins": 198,
        "documents": 184,
        "municipalTaxRows": 17,
        "textBlocks": 29738
      }
    },
    {
      "path": "tmp/reports/procurement-supabase-import.sql",
      "rows": {
        "acts": 473,
        "bulletins": 108,
        "supplierLines": 2695,
        "suppliers": 358
      }
    },
    {
      "path": "tmp/reports/public-site-supabase-import.sql",
      "rows": {
        "councilors": 26,
        "news": 3,
        "projects": 4,
        "searchRows": 42,
        "sessions": 3,
        "snapshots": 1,
        "staffGroups": 4,
        "staffPeople": 6
      }
    },
    {
      "path": "tmp/reports/ai-search-supabase-refresh.sql",
      "rows": {
        "searchDocuments": 30527
      }
    },
    {
      "path": "tmp/reports/public-site-api-supabase-import.sql",
      "rows": {
        "councilors": 26,
        "news": 3,
        "projects": 4,
        "searchRows": 42,
        "sessions": 3,
        "snapshots": 1,
        "staffGroups": 4,
        "staffPeople": 6
      }
    },
    {
      "path": "tmp/reports/legislative-admin-supabase-import.sql",
      "rows": {
        "blocks": 7,
        "councilors": 26,
        "documents": 0,
        "news": 3,
        "projectAuthors": 8,
        "projectTags": 8,
        "projectVotes": 104,
        "projects": 4,
        "sessionAttendance": 0,
        "sessions": 3,
        "staff": 6
      }
    }
  ],
  "fallbackFiles": [
    "/data/ai-catalog.json",
    "/data/boletines/historicos-index.json",
    "/data/boletines/landing-summary.json",
    "/data/boletines/sibom-index.json",
    "/data/boletines/wordpress-index.json",
    "/data/tasas/tasas-2025.json",
    "/data/transparencia/rendicion-2025.json"
  ]
}
