Connect data sources

PostgreSQL

Automata accepts a PostgreSQL connection string, proves it before saving, and exposes catalog, query, and optional write tools through a connector token.

Create a database role

The database role is the real security boundary. Start with only the schemas and tables the connector requires:

CREATE ROLE automata_reader LOGIN PASSWORD '<strong-password>';
GRANT CONNECT ON DATABASE app TO automata_reader;
GRANT USAGE ON SCHEMA public TO automata_reader;
GRANT SELECT ON public.customers, public.invoices TO automata_reader;

Add the connection

Create a PostgreSQL database connection and paste the DSN:

postgresql://automata_reader:<password>@db.example.com:5432/app?sslmode=require

Automata connects before saving. Rotating the connection string later does not invalidate connector tokens because tokens identify the connection, not the current credential.

Read and write access

New PostgreSQL tokens start with read tools enabled and run-statement disabled. For controlled writes, grant the exact INSERT, UPDATE, or DELETE privileges to the role, then explicitly add run-statement to the token.

Query safeguards

Every statement is restricted to one extended-protocol statement and checked with EXPLAIN (FORMAT JSON, VERBOSE) before execution.

  • run-query accepts SELECT, WITH, VALUES, or TABLE in a read-only transaction.
  • run-statement accepts only INSERT, UPDATE, DELETE, or MERGE.
  • DDL, TRUNCATE, COPY, and CREATE TABLE AS are refused.
  • Functions outside pg_catalog, SECURITY DEFINER functions, and dangerous built-ins are refused.
  • Writes over maxRows roll back in full.
  • UPDATE and DELETE without WHERE require allowWholeTable: true.
  • Every table in the plan must be in the token's table allowlist, or the statement is refused before it runs.

What plan checks cannot see

The plan describes the statement, not everything it may trigger. Triggers and the bodies of user-defined functions can do more than the plan shows, and a superuser can bypass normal database restrictions. This is why the role, not the token scope, is the real boundary.

Private network targets

The outbound host guard rejects private and loopback destinations by default. Set NUXT_ALLOW_PRIVATE_TARGETS=true only for local or single-tenant self-hosting where private connectivity is intentional.

Automata always refuses targets that resolve to its own database (NUXT_DATABASE_URL), Evolution API, or Evolution database, regardless of that setting. The guard runs whenever a connection is opened, and the approved address is pinned so the name cannot be re-resolved elsewhere.

The app warns when the connecting role is a superuser.

View source