Acceso a bases de datos PostgreSQL para creadores de aplicaciones de IA
Configura el acceso a una base de datos PostgreSQL para un creador de aplicaciones de IA con descubrimiento de solo lectura, credenciales limitadas, migraciones aprobadas y pooling seguro.

Un creador de aplicaciones de IA puede conectarse a una base de datos PostgreSQL existente sin ser propietario de su esquema, pero solo si haces que ese límite sea real en PostgreSQL. Un prompt que diga «no cambies producción» no es un control. Un rol independiente, valores predeterminados de transacción, revisión explícita de migraciones y comprobaciones del esquema sí lo son.
El modelo seguro divide el trabajo de la base de datos en tres vías. El descubrimiento lee metadatos y muestras de datos permitidos. La aplicación solo lee y escribe en las tablas y operaciones que necesita. Los cambios de esquema se ejecutan mediante una identidad de migración independiente después de que una persona apruebe el SQL exacto. He visto equipos juntar esas vías en una cómoda credencial de propietario y descubrir después que un agente tomó un nombre de columna plausible como permiso para rediseñar una tabla activa. La comodidad duró una tarde; la limpieza llevó mucho más tiempo.
El descubrimiento debe ser de solo lectura por diseño
Una conexión de descubrimiento necesita acceso suficiente para entender el esquema permitido, no para mejorarlo. Crea un rol de inicio de sesión que no pueda crear bases de datos ni roles, no pueda omitir la seguridad de filas y no pueda heredar privilegios inesperados de un grupo amplio. PostgreSQL crea roles nuevos sin esos poderes, pero declararlos explícitamente hace que la intención pueda revisarse.
CREATE ROLE app_discovery
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
NOINHERIT
NOBYPASSRLS
CONNECTION LIMIT 3
PASSWORD 'replace-through-secret-manager';
ALTER ROLE app_discovery SET default_transaction_read_only = on;
GRANT CONNECT ON DATABASE customer_portal TO app_discovery;
GRANT USAGE ON SCHEMA app TO app_discovery;
GRANT SELECT ON ALL TABLES IN SCHEMA app TO app_discovery;
default_transaction_read_only bloquea las escrituras normales en sesiones que mantienen el valor predeterminado. Es un buen refuerzo, no la protección principal. La ausencia de INSERT, UPDATE, DELETE, TRUNCATE, CREATE y propiedad es lo que mantiene contenido al rol si un cliente cambia la configuración de la transacción. No concedas al rol pertenencia a un grupo propietario de la aplicación ni lo conviertas en propietario de un esquema.
Conviene inspeccionar los permisos existentes antes de que se conecte el creador. La siguiente consulta genera una fila por cada privilegio de tabla, para que un revisor pueda detectar cualquier cosa que vaya más allá de SELECT:
SELECT table_schema, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'app_discovery'
ORDER BY table_schema, table_name, privilege_type;
Un resultado correcto tiene una forma como app | invoices | SELECT. Un resultado vacío puede indicar que el descubrimiento no ve una tabla necesaria; una fila que termina en UPDATE significa que el rol tiene demasiado poder. Comprueba también los privilegios de esquema con has_schema_privilege y los privilegios de base de datos con has_database_privilege, porque los permisos de tabla no revelan si el rol puede crear objetos en otro lugar.
No uses una instantánea de producción como excusa para compartir una credencial de propietario. Una copia puede seguir conteniendo datos de clientes, y un agente con propiedad puede alterarla tanto que las comparaciones posteriores dejen de servir. Da al descubrimiento una identidad dedicada en todos los entornos.
La inspección del catálogo debe mantenerse dentro de una lista permitida
El creador debe descubrir solo esquemas aprobados y registrar lo que PostgreSQL informa realmente. information_schema ofrece vistas portables de tablas, columnas, restricciones y privilegios. pg_catalog expone detalles de PostgreSQL como índices, tipos, expresiones generadas y seguridad de filas. Ambas fuentes son mejores que la memoria de un LLM sobre una tabla típica de clientes.
Empieza con una lista permitida como app y reporting. Rechaza pg_catalog, information_schema, los esquemas temporales, los esquemas de extensiones y cualquier esquema de tenant que no figure en la lista como destino de la aplicación. La consulta debe filtrar en los niveles de base de datos, rol y SQL; una lista permitida solo en el prompt puede desaparecer durante un chat posterior.
SELECT
c.table_schema,
c.table_name,
c.ordinal_position,
c.column_name,
c.data_type,
c.is_nullable,
c.column_default
FROM information_schema.columns AS c
WHERE c.table_schema IN ('app', 'reporting')
ORDER BY c.table_schema, c.table_name, c.ordinal_position;
Guarda el resultado como una instantánea del esquema con una hora de obtención y un identificador de la base de datos. La instantánea prueba lo que vio el generador. No es una verdad permanente. PostgreSQL puede cambiar entre el descubrimiento y la generación de código, así que compara una huella digital reciente antes del despliegue. Una huella práctica puede calcular un hash de descripciones ordenadas de tablas, columnas, tipos, nulabilidad, valores predeterminados, restricciones e índices. Si la huella cambia, detente y vuelve a descubrir el esquema en vez de adivinar qué cambio es inocuo.
Muestrear filas es una decisión de permisos aparte. Los metadatos de columnas rara vez contienen datos personales, mientras que las muestras de filas suelen contenerlos. Para generar código, es preferible no muestrear filas. Si hacen falta ejemplos, expón una vista que elimine o enmascare secretos e identificadores directos, y concede SELECT únicamente sobre esa vista. LIMIT 10 no vuelve segura una consulta sensible; solo reduce el tamaño de la filtración.
La ruta de búsqueda merece el mismo cuidado. Establécela en el esquema aprobado más pg_catalog, califica los nombres de tabla generados y nunca dependas del objeto que PostgreSQL resuelva primero. Un atacante o una migración descuidada puede crear un objeto con el mismo nombre en un esquema con escritura. Los nombres calificados como app.orders eliminan esa ambigüedad.
El rol de ejecución debe ajustarse a las acciones reales de los usuarios
El descubrimiento y la ejecución son trabajos distintos. La aplicación en ejecución puede necesitar insertar un pedido, actualizar un borrador o llamar a una función diseñada con cuidado, pero eso no justifica acceso de escritura amplio en todo el esquema descubierto. Elabora una matriz de permisos a partir de las acciones de los usuarios y traduce cada acción al permiso mínimo de PostgreSQL.
Por ejemplo, un visor de facturas puede necesitar SELECT en app.invoices y app.invoice_lines, mientras que una función de notas necesita SELECT e INSERT en app.invoice_notes. Probablemente no necesita DELETE en facturas, acceso a registros de restablecimiento de contraseñas ni creación de esquemas. Concede uso de secuencias solo cuando una inserción dependa realmente de esa secuencia. PostgreSQL trata las secuencias como objetos independientes, algo que sorprende a los generadores que prueban con una cuenta de propietario.
Las vistas y las funciones pueden reducir aún más la superficie. Una vista puede exponer columnas aprobadas y ocultar campos internos. Una función SECURITY DEFINER puede realizar una operación controlada que los permisos ordinarios no expresan, pero necesita una search_path fija, validaciones estrictas de entrada y un propietario que no tenga poderes innecesarios. Trata esa función como código privilegiado, no como un atajo para eludir el modelo de permisos.
La seguridad a nivel de fila añade un límite de datos dentro de una tabla compartida. No sustituye los permisos de tabla. PostgreSQL primero comprueba si el rol puede realizar la operación y luego aplica las políticas de seguridad de filas cuando están habilitadas y corresponden. Prueba con el rol de ejecución exacto, porque los propietarios de tablas y los roles con BYPASSRLS pueden eludir las políticas. Una prueba realizada con el propietario de migración casi no demuestra nada sobre lo que puede ver un usuario final.
Mantén los secretos fuera de los prompts, el código generado, los paquetes del navegador, los registros de compilación y las capturas de pantalla. Guarda la credencial de ejecución en el almacén de secretos del entorno de alojamiento e inyéctala únicamente en el proceso de servidor. Las aplicaciones móviles y de navegador no pueden mantener secreta una contraseña de PostgreSQL, así que deben llamar a una API de servidor en lugar de conectarse directamente. Rota de forma independiente las credenciales de descubrimiento, ejecución y migración; una filtración en una vía no debería abrir las otras dos.
El poder de migración pertenece a una ruta de aprobación independiente
Un creador de aplicaciones puede proponer migraciones, pero no debe ejecutarlas con su sesión de descubrimiento o de ejecución. Da al trabajo de migración un rol independiente, o permite que un sistema de despliegue consolidado asuma ese rol para un único trabajo aprobado. Mantén su credencial fuera de las sesiones normales de chat y vista previa.
La aprobación debe cubrir el SQL exacto, la identidad de la base de datos de destino, la huella del esquema usada para prepararlo y el comportamiento esperado de bloqueo o reescritura. Aprobar una frase en lenguaje natural como «añadir estado del cliente» deja demasiado margen. El cambio ejecutable podría añadir una columna de texto anulable, reconstruir una tabla grande, inventar un enum o actualizar todas las filas existentes. Son operaciones distintas con modos de fallo distintos.
Uso un paquete de migración compacto:
- El motivo del cambio y la versión de la aplicación que lo requiere.
- SQL exacto de avance y, cuando sea honesto, SQL exacto de reversión.
- Objetos, privilegios y filas que los comandos pueden afectar.
- Consultas previas, resultados esperados y una huella reciente del esquema.
- Tiempo de espera de bloqueo, tiempo de espera de sentencia, referencia de copia de seguridad o instantánea y responsable del lanzamiento.
Un script de reversión no siempre es una vuelta atrás. Eliminar una columna recién añadida puede revertir el cambio de catálogo, pero también destruye los datos escritos tras el lanzamiento. El DDL transaccional de PostgreSQL ayuda con muchas operaciones de catálogo, pero una transacción no puede restaurar efectos externos ni datos que un comando posterior eliminó. Etiqueta claramente las reversiones destructivas en vez de tratar DOWN como una palabra mágica.
Configura lock_timeout para que una migración falle en lugar de esperar tras una transacción ocupada mientras bloquea trabajo nuevo. Configura statement_timeout según la operación revisada. Ejecuta de nuevo las consultas previas dentro de la ventana de cambio. Si el tamaño de la tabla, los objetos en conflicto, los recuentos de valores nulos o la huella del esquema difieren de los supuestos aprobados, cancela. El agente debe devolver un informe de discrepancias, no improvisar una migración nueva contra producción.
Nunca apruebes automáticamente una migración porque hayan pasado las pruebas generadas. Las pruebas suelen ejecutarse sobre un esquema pequeño y limpio, y no detectan colas de bloqueos, valores nulos antiguos, restricciones inusuales, extensiones ni versiones de la aplicación que aún atienden tráfico. La aprobación es el momento en que una persona concilia la intención generada con el sistema activo.
El pool de conexiones cambia el cálculo de seguridad
Un pool reutiliza sesiones de base de datos, por lo que el estado de sesión puede sobrevivir a la solicitud que lo creó. Si una solicitud ejecuta SET search_path, cambia un rol, crea un objeto temporal o desactiva un tiempo de espera, el siguiente usuario de la conexión puede heredar el resultado. La aplicación debe evitar el estado de sesión mutable o restablecerlo de forma fiable cuando una conexión vuelve al pool.
El pool de transacciones hace el límite más estricto. Un cliente puede recibir una sesión de servidor diferente después de cada transacción, lo que rompe las suposiciones sobre sentencias preparadas de sesión, tablas temporales, bloqueos consultivos y configuraciones de nivel de sesión. Los creadores suelen generar código que funciona mediante una conexión directa y falla detrás de un pool porque nunca modelan esta diferencia. Decide si el pool usa modo de sesión o de transacción, e incluye ese modo en la generación y las pruebas.
Calcula el presupuesto de conexiones antes del despliegue. Empieza por las conexiones permitidas de la base de datos, reserva capacidad para administración, migraciones, supervisión y otros servicios, y divide el resto entre las instancias de la aplicación. Si diez instancias abren veinte conexiones cada una, PostgreSQL ve doscientas sesiones potenciales incluso cuando el tráfico es bajo. Un pool pequeño y prudente con una cola suele ser más seguro que multiplicar conexiones hasta que la base de datos las rechace.
Usa tiempos de espera del lado del servidor como respaldo: statement_timeout limita las sentencias largas, lock_timeout limita las esperas de bloqueos e idle_in_transaction_session_timeout elimina sesiones que mantienen una transacción abierta sin hacer nada. Define valores para cada rol en lugar de confiar en que todos los clientes generados lo recuerden. Verifícalos con SHOW bajo el rol real y a través del pool real.
Las comprobaciones de estado deben ser baratas. SELECT 1 confirma un recorrido de ida y vuelta, pero no confirma que la aplicación pueda acceder a una tabla aprobada ni que su ruta de búsqueda sea correcta. Una comprobación de disponibilidad puede consultar una vista pequeña y estable con el rol de ejecución. Mantén las migraciones fuera del inicio de la aplicación; varias instancias compitiendo por modificar el esquema crean justo el acoplamiento que este diseño busca eliminar.
Las columnas inventadas deben fallar antes de ejecutar una consulta
Los LLM inventan identificadores plausibles. Si un prompt habla del nombre para mostrar de un cliente, el código generado puede intentar usar customers.display_name aunque la base de datos guarde given_name y family_name. La base de datos rechazará esa consulta, lo cual es mejor que leer silenciosamente el campo equivocado, pero un error de producción sigue siendo una mala estrategia de validación del esquema.
Genera un artefacto de esquema tipado a partir de la instantánea aprobada del catálogo y conviértelo en la única fuente para construir consultas. Una tabla o columna ausente de ese artefacto debe provocar un error de generación. No permitas que el modelo repare el error añadiendo una migración salvo que la tarea entre explícitamente en la vía de migración. Un identificador ausente puede indicar un descubrimiento obsoleto, un error ortográfico, el entorno equivocado o una necesidad real del producto. Cada caso requiere una respuesta distinta.
Las comprobaciones estáticas deben analizar el SQL y resolver cada relación y columna frente a la instantánea. Después, prepara las sentencias frente a una base de datos desechable o una transacción que no pueda escribir. El analizador de PostgreSQL detecta columnas desconocidas, referencias ambiguas, errores de tipos de operadores y muchas conversiones incorrectas sin necesitar datos de negocio válidos. Ejecuta pruebas de integración con el rol de ejecución para que participen los permisos y las políticas de filas.
El informe de fallo necesita suficiente detalle para que una persona decida. Incluye la ubicación del SQL, el identificador no resuelto, identificadores válidos cercanos, la huella de la instantánea y la identidad de la base de datos de destino. Las sugerencias son útiles, pero el reemplazo automático por similitud es peligroso. Cambiar billing_address_id por shipping_address_id porque los nombres se parecen puede generar SQL válido con un significado de negocio falso.
Para filtros y ordenaciones dinámicos, asigna los nombres públicos de la API a un conjunto cerrado de expresiones SQL calificadas. Nunca pegues en SQL un identificador proporcionado por un modelo, ni siquiera junto a un parámetro de valor. Los parámetros protegen valores, no nombres de tablas o columnas. Si los usuarios pueden elegir un campo de ordenación, traduce created a una expresión conocida como app.orders.created_at; rechaza cualquier token desconocido.
La deriva del esquema debe detener un lanzamiento, no provocar una conciliación creativa. Regenera la instantánea, muestra las diferencias y repite las pruebas. Esa demora puede parecer quisquillosa, pero es más barata que desplegar código cuyo entendimiento de la base de datos solo existe en una transcripción de conversación.
El SQL destructivo necesita una política de denegación y pruebas
Un creador debe clasificar el SQL antes de que alguien pueda ejecutarlo. Bloquea DROP, TRUNCATE, DELETE o UPDATE amplios sin un predicado revisado, cambios de propiedad, escalada de privilegios, cambios de extensiones y comandos dirigidos fuera de los esquemas aprobados. Trata ALTER TABLE como una operación que exige revisión, no como algo seguro automáticamente. Un cambio de tipo de columna o una nueva restricción no nula puede analizar o reescribir datos y mantener bloqueos importantes.
La coincidencia de texto por sí sola es débil porque el SQL tiene comentarios, identificadores entre comillas, funciones y muchas formas de expresar efectos secundarios. Analiza las sentencias con un analizador compatible con PostgreSQL, inspecciona sus árboles de sintaxis y confía también en que el rol de la base de datos deniegue las acciones prohibidas. El clasificador mejora la revisión; los privilegios imponen el límite. Ninguno debe cargar con toda la responsabilidad.
Usa una base de datos de preparación restaurada desde una instantánea reciente y debidamente protegida cuando una migración dependa de formas reales de tablas o distribuciones de datos. Aplica allí el paquete de migración exacto, registra observaciones de duración y bloqueos, ejecuta pruebas de la aplicación con credenciales de ejecución y después descarta el entorno. No edites el SQL de forma silenciosa entre preparación y producción. Cualquier edición crea un artefacto nuevo que necesita una huella y aprobación nuevas.
Los registros deben conectar una propuesta con una ejecución sin guardar secretos ni filas sensibles. Registra quién aprobó el artefacto de migración inmutable, su resumen criptográfico, la identidad de destino, el estado de inicio y finalización, y los detalles de los errores de PostgreSQL. Conserva las diferencias generadas y los resultados previos. Un chat con un agente aporta contexto útil, pero no es un registro de auditoría porque los usuarios pueden bifurcar, reintentar y parafrasear instrucciones.
Las instantáneas y los controles de reversión reducen el tiempo de recuperación, pero no vuelven aceptable el SQL destructivo. Una instantánea puede restaurar una base de datos completa a un punto anterior cuando la necesidad real es una sola columna eliminada, y la restauración puede descartar escrituras legítimas realizadas después de la instantánea. Prueba la recuperación por separado y documenta quién puede activarla.
Cuando uso Koder.ai para una aplicación que toca una base de datos consolidada, mantengo el trabajo en modo de planificación hasta revisar el código exportado y el límite de base de datos propuesto; las instantáneas y la reversión son controles de recuperación, no permiso para saltarse esa revisión. La misma regla se aplica a cualquier creador: la comodidad del producto debe estar detrás de la aplicación de reglas por la base de datos.
Los cambios de esquema deben tolerar versiones mixtas de la aplicación
Una migración solo es segura cuando tanto la aplicación antigua como la nueva pueden ejecutarse durante la ventana de lanzamiento. Producción rara vez pasa de una versión a otra en un único instante. Las solicitudes pueden llegar a instancias antiguas mientras arrancan las nuevas, los trabajos en cola pueden llevar cargas antiguas y una reversión puede devolver el código de ayer frente al esquema de hoy. Un creador de aplicaciones que valida solo el código final frente al esquema final no detecta este solapamiento.
Prioriza los cambios aditivos. Añade una columna anulable, una tabla nueva o un índice sin quitar la ruta antigua. Despliega código que pueda leer ambas representaciones y escriba la nueva cuando corresponda. Rellena las filas existentes mediante un trabajo revisado por separado, vigila los errores y el retraso, y después convierte el campo nuevo en el autoritativo. Elimina la columna o restricción anterior en una versión posterior, cuando la evidencia muestre que ningún código en ejecución la usa.
Esta secuencia tarda más que generar una sentencia ALTER TABLE, pero aísla los fallos. Si el código nuevo se comporta mal antes de eliminar nada, la ruta antigua sigue existiendo. Si un relleno se retrasa, puede pausarse sin retener el lanzamiento de la aplicación. Si el despliegue se revierte, la aplicación antigua sigue reconociendo la base de datos. Una versión adicional cuesta menos que descubrir durante la reversión que el binario anterior consulta una columna que la migración ya eliminó.
Los cambios de nombre exigen especial cuidado porque PostgreSQL cambia el nombre de inmediato. Un generador puede proponer cambiar customer_ref por customer_id porque el nuevo nombre se lee mejor. Las instancias antiguas fallarán en cuanto se confirme la migración. Añade customer_id, mantén ambos campos sincronizados en el código de la aplicación o mediante un trigger revisado de forma limitada, mueve los lectores y elimina customer_ref solo cuando desaparezcan los escritores antiguos. La duplicación temporal es una deuda visible con una condición de eliminación; un cambio de nombre inmediato es un acoplamiento de lanzamiento invisible.
Los valores predeterminados y las restricciones no nulas también pueden ocultar trabajo. Antes de aprobar SET NOT NULL, cuenta los valores nulos existentes y demuestra que todos los escritores activos proporcionan un valor. Para tablas grandes o con mucha actividad, revisa cómo valida la restricción la versión de PostgreSQL y qué bloqueos toma. Un creador debe informar esas condiciones previas en lugar de deducirlas de un esquema que no contiene tráfico representativo.
Los rellenos de datos no deben ejecutarse dentro de una transacción de esquema sin límite. Actualiza filas en lotes medidos mediante un trabajador aprobado, registra el progreso con un cursor estable y haz que los reintentos sean idempotentes. Un reintento es idempotente cuando aplicarlo dos veces produce el estado deseado, no solo cuando PostgreSQL acepta la segunda consulta. Para valores derivados, registra la versión de derivación si el código posterior pudiera calcularlos de otro modo.
El paquete de lanzamiento debe nombrar cuatro puntos de compatibilidad:
- La versión más antigua de la aplicación que puede ejecutarse antes de la migración.
- El estado de esquema aceptado por las versiones antigua y nueva.
- La señal que permite la versión de limpieza destructiva.
- La ruta de recuperación si el código nuevo se revierte después de que cambien los datos.
Las consultas generadas deben evitar SELECT * durante estas transiciones. Añadir una columna puede cambiar el coste de análisis, la decodificación de resultados, la asignación posicional y la exposición de datos aunque el SQL antiguo siga analizándose. Enumera explícitamente las columnas calificadas y genera los decodificadores a partir de la misma instantánea del esquema. Así, una revisión del código revela exactamente qué datos cruzan el límite de la base de datos.
Las herramientas de migración preparadas suelen registrar una versión aplicada en una tabla, pero un número de versión por sí solo no demuestra compatibilidad. Registra el resumen criptográfico del artefacto SQL exacto, porque dos archivos con el mismo nombre reconocible pueden contener comandos distintos. El ejecutor debe rechazar una versión ya registrada con un resumen diferente. También debe rechazar una migración posterior cuando falte un predecesor necesario.
No permitas que todas las instancias de la aplicación ejecuten migraciones al iniciarse. Incluso cuando una herramienta de migración use un bloqueo consultivo, el inicio pasa a depender de una credencial privilegiada y de que el trabajo de esquema termine antes de que expiren las comprobaciones de estado. Ejecuta las migraciones en un único trabajo de lanzamiento, espera su resultado registrado e inicia las instancias de ejecución con una identidad que no pueda modificar el esquema. Si el sistema de lanzamiento no puede separar esas fases, corrígelo antes de conceder poderes de propietario a la aplicación.
Prueba esta línea temporal, no solo el destino: código antiguo con esquema antiguo, código antiguo con esquema ampliado, código nuevo con esquema ampliado y código revertido después de nuevas escrituras. La limpieza recibe su propia prueba más adelante. Esta matriz detecta cambios que son sintácticamente válidos pero imposibles de revertir en la práctica.
Demuestra el límite con pruebas negativas
Un diseño de seguridad está incompleto hasta que las acciones prohibidas fallan en pruebas. Conéctate como descubrimiento e intenta una inserción, la creación de una tabla y un SET TRANSACTION READ WRITE. Conéctate como ejecución e intenta acceder a una tabla sin permisos, leer entre tenants cuando la seguridad de filas lo impida y cambiar el esquema. El resultado esperado es un error de permisos de PostgreSQL, no una promesa en el registro de un agente.
Ejecuta también pruebas positivas. El descubrimiento debe seguir leyendo cada entrada permitida del catálogo. La ejecución debe realizar cada acción de usuario aprobada a través del pool. La ejecución de migraciones debe funcionar únicamente mediante la ruta de aprobación. Un límite que bloquea el trabajo normal del producto invitará a alguien a sustituirlo por una credencial de propietario durante un incidente.
Mantén un pequeño contrato de acceso junto al código fuente de la aplicación. Debe nombrar la base de datos, los esquemas permitidos, el alcance de descubrimiento, las operaciones de ejecución, el modo del pool, la política de tiempos de espera, los aprobadores de migraciones, el método de huella del esquema y las sentencias prohibidas. Compara los permisos reales con ese contrato en comprobaciones continuas. La deriva de permisos de PostgreSQL es deriva de configuración, incluso cuando nadie cambió el código de la aplicación.
Vuelve a comprobarlo después de cambios de roles, tablas nuevas, bases de datos restauradas, actualizaciones del pool y cambios de alojamiento. Los privilegios predeterminados importan para objetos futuros: conceder SELECT ON ALL TABLES cubre las tablas actuales, no las que se creen después. Decide si los objetos nuevos deben ser invisibles hasta su revisión o incluirse mediante privilegios predeterminados configurados de forma limitada. Prefiero que sean invisibles por defecto porque un permiso explícito obliga a incluir la nueva tabla en la conversación sobre acceso.
Incluye la revocación en el plan de pruebas. Desactiva la credencial de descubrimiento y confirma que el tráfico de ejecución continúa; desactiva la de ejecución y confirma que las herramientas de migración no sustituyen silenciosamente su identidad más fuerte. Después, rota cada secreto mientras haya conexiones activas y observa si el pool retira las sesiones antiguas dentro de la ventana prevista. Un cambio de contraseña no termina las sesiones ya autenticadas, por lo que los procedimientos de rotación necesitan un reciclaje explícito del pool o una política de terminación de sesiones de PostgreSQL.
Revisa los mensajes de error para detectar divulgación accidental durante estas pruebas. Los errores de PostgreSQL pueden incluir nombres de relaciones, fragmentos de SQL, nombres de restricciones y valores proporcionados. Envía los errores detallados a registros de servidor restringidos, devuelve un error público estable a los clientes y nunca introduzcas un flujo completo de errores de producción en una conversación con un agente. El creador necesita la ubicación de la sentencia y la respuesta de base de datos depurada para reparar código; no necesita valores de clientes.
Una última prueba detecta una cantidad sorprendente de integraciones inseguras: elimina por completo la credencial de migración y ejecuta el conjunto de pruebas de la aplicación. Si el inicio normal, las comprobaciones de estado, las vistas previas o la gestión de solicitudes fallan, la propiedad del esquema se ha filtrado a la ruta de ejecución. Corrige ese acoplamiento antes de conectar el creador a producción. Un creador de aplicaciones de IA puede trabajar con una base de datos que no posee, pero PostgreSQL debe poder decir que no cuando el código generado olvide el acuerdo.
Preguntas frecuentes
¿Puede un creador de aplicaciones de IA usar mi base de datos PostgreSQL actual?
Sí, si el creador se conecta mediante roles dedicados y descubre únicamente los esquemas aprobados. Mantén el descubrimiento, las consultas en ejecución y las migraciones en rutas de permisos separadas para que conectar la herramienta no le otorgue propiedad sobre el esquema.
¿Un usuario de PostgreSQL de solo lectura garantiza que no cambiarán los datos?
Un rol que solo tenga SELECT y no sea propietario de objetos es el control principal. default_transaction_read_only añade protección, pero no debe compensar permisos amplios ni pertenencias heredadas.
¿Debo dar al creador la contraseña de propietario de mi base de datos?
No. Una credencial de propietario elimina el límite y permite que el SQL generado cambie permisos, tablas y datos. Crea credenciales separadas para el descubrimiento, la ejecución y el trabajo controlado de migración.
¿Cómo puede un creador de aplicaciones conocer mi esquema de forma segura?
Permite que consulte las vistas aprobadas de information_schema y pg_catalog mediante un rol limitado, y guarda después una instantánea con huella digital. Evita muestrear filas salvo que hayas preparado una vista enmascarada para ello.
¿Qué ocurre cuando la IA inventa una columna de PostgreSQL?
La generación debe fallar frente a una instantánea de esquema tipada antes del despliegue. Informa del nombre desconocido y de nombres válidos cercanos, pero deja que una persona decida si la solución es código, un nuevo descubrimiento o una migración aprobada.
¿Puede la aplicación conectarse directamente desde un navegador o una aplicación móvil?
No debería conectarse directamente a PostgreSQL, porque esos clientes no pueden mantener secreta una contraseña de base de datos. Coloca el acceso a la base de datos en un proceso de servidor y deja que el navegador o la aplicación móvil llame a su API.
¿Necesito un pool de conexiones para aplicaciones generadas?
Normalmente sí, pero configúralo de forma deliberada. Limita el total de sesiones, elige el modo de sesión o de transacción, restablece el estado modificable y prueba el código generado con el mismo pool que usarás en producción.
¿Se pueden revertir de forma segura las migraciones de PostgreSQL?
Algunos cambios de catálogo se revierten limpiamente dentro de una transacción, pero la pérdida de datos y los efectos externos no. Revisa por separado el SQL de avance y de reversión, y trata las instantáneas como herramientas de recuperación, no como prueba de que un cambio es seguro.
¿Cómo evito que el creador cambie tablas no aprobadas?
Usa listas de esquemas permitidos, nombres calificados, permisos mínimos, una política de SQL analizado y pruebas negativas de permisos. El rol de PostgreSQL debe rechazar la operación aunque el modelo o el verificador de políticas se equivoquen.
¿Con qué frecuencia debe el creador volver a descubrir el esquema?
Vuelve a descubrir el esquema cuando cambie la huella almacenada y después de migraciones, restauraciones o cambios de entorno. No lo actualices de forma silenciosa durante un despliegue: muestra las diferencias y vuelve a validar con la nueva instantánea.