Help · Safety

Safe reads and agent access

The two ways saferow keeps reads from writing, how to make a SELECT-only user, what the Safe reads step’s messages mean, and what agent access allows.

Every read the agent or an MCP client makes is a safe read, and never asks. A safe read runs one of two ways, set per connection in Connection Settings › Safe reads (“Safe reads run as”):

The status bar says which: “Safe reads: your user” or “Safe reads: a SELECT-only user”.

Making a SELECT-only user

Press Make a SELECT-only user for me. saferow writes the SQL, and you approve each statement, one at a time, running as your own user. It makes a strong password and puts it straight into your Keychain; the statements say :password, and saferow fills it in only as they run. On MySQL (the connection’s database must be set first):

CREATE USER 'saferow_ro'@'%' IDENTIFIED BY :password
    GRANT SELECT, SHOW VIEW ON `shop`.* TO 'saferow_ro'@'%'

On Postgres, for each schema that holds tables:

CREATE ROLE "saferow_ro" LOGIN PASSWORD :password
    GRANT CONNECT ON DATABASE "shop" TO "saferow_ro"
    GRANT USAGE ON SCHEMA "public" TO "saferow_ro"
    GRANT SELECT ON ALL TABLES IN SCHEMA "public" TO "saferow_ro"
    ALTER DEFAULT PRIVILEGES IN SCHEMA "public" GRANT SELECT ON TABLES TO "saferow_ro"
    ALTER ROLE "saferow_ro" SET default_transaction_read_only = on

Check it any time with SHOW GRANTS FOR 'saferow_ro'@'%' on MySQL, or \du and \dp in psql. saferow checks the user’s grants each time it connects.

When the Safe reads step fails

On SQLite, saferow opens the file read-only for reading, behind an authorizer that allows only reads, so no user is needed.

Agent access

The last step says what the agent and saferow mcp may do on this connection:

Run the self-test from Settings › Safety (“Verify, don’t trust”) to see which guard stops each known escape on your own database.

Still stuck? In saferow, choose Help › Report a Problem…, or write to support. Please leave out passwords, keys and real data.