What the agent does
The agent clones the repository into its own cloud sandbox and reads the project first. In the Supabase doc search starter supabase-community/nextjs-openai-doc-search it finds a pnpm project (pnpm-lock.yaml and pnpm-workspace.yaml sit beside package.json), Next.js 13.2.4 with @supabase/supabase-js ^2.13.0, and no test script at all, so the tests the issue asks for are new ground rather than an existing suite to extend.
The database schema lives in supabase/migrations/20230406025118_init.sql. It creates the pgvector extension and two tables, public.nods_page and public.nods_page_section, and both already run alter table ... enable row level security. That is the catch the issue is really about: RLS is enabled with zero policies, so the anon role can read nothing at all, and the search function match_page_sections(embedding vector(1536), match_threshold float, match_count int, min_content_length int) is created without security definer, so it runs with the rights of whoever calls it.
The app explains why that matters. pages/api/vector-search.ts, an edge API route, builds a Supabase client with SUPABASE_SERVICE_ROLE_KEY and calls rpc('match_page_sections', …), and lib/generate-embeddings.ts writes the sections with the service key at build time. The service role bypasses RLS by design, so embeddings flow in and search answers through it while anon sits behind an empty policy set. The migration the issue asks for closes the middle ground: anon keeps a path into the data only by executing the match function, direct select on both tables stays closed to it, and service-role writes keep working.
The agent writes that as a new migration under supabase/migrations/ with the pgTAP tests beside it in supabase/tests/: anon can execute match_page_sections but cannot select from nods_page or nods_page_section, and cannot insert into either, and the tests say so against a real database. The local stack is Postgres 15 (major_version = 15 in supabase/config.toml), and the agent runs supabase db test against it, then pnpm build so the Next.js app still compiles with the new migration in place.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "A Linear issue labeled agent says: \"Add Row Level Security Policies to a Supabase Project. Enable row level security on every table, allow anon read only through the match function and service role writes, as a new migration with pgTAP tests.\" Do the work in this repository, add tests for it, run supabase db test and pnpm build, and open a pull request that links back to the issue.",
"resources": [
{
"url": "https://github.com/your-org/your-app"
}
]
}- Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
- Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
- Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.
What comes back
What comes back is a pull request: one new migration file, a supabase/tests/ directory with the pgTAP tests, and no changes to pages/api/vector-search.ts or the embedding writer, because the service-role path already works and the migration only rearranges what anon can reach.
The checks run the commands the issue names. supabase db test exercises each policy against a real Postgres, and pnpm build proves the app compiles. A reviewer reads the migration for the three promises it makes: anon executes the match function, direct table reads stay closed, and service-role writes are untouched. The pgTAP tests are the part to read closely, because they fail if any policy is widened later.
The session read keeps the whole record: the migration applied, each test file with its result, and the build output, so every claim in the pull request description can be traced to a command and its output.
Run it on every Linear issue labelled agent
This job is one instance of the Linear label automation. An automation on the Project watches for linear.issue.labeled with the agent label and starts a run with this prompt, so each schema or security issue becomes a run without anyone copying text between tools.
Runs can also be started from a server that receives Linear's webhooks and POSTs the same body to /o/{org}/sessions, with the issue text in input. Set a webhook URL on the API key and Rush posts run.completed to it when the turn finishes, so the server learns the pull request is ready without polling.
The use case this job follows, with its automation and trigger: Turn a Linear label into a PR.
Why run it on Rush?
pgTAP tests only mean something against a real Postgres. On a laptop that means a local Supabase stack running before every supabase db test. Each run on Rush boots a sandbox where the CLI and the database start together, and the run keeps every command and its output, so the proof that anon cannot read a table is a recorded test, not an assertion in the pull request description.
And one issue never waits behind another. A labelled migration issue and a labelled policy issue start as two runs in two sandboxes, each with its own branch, its own migration and its own pull request.
Frequently asked questions
The tables already have RLS enabled. What is there to add?
Enabled with no policies means anon can do nothing; the starter relies on the service role for all reads and writes. The migration adds the only intended anon path, execution of match_page_sections, and the pgTAP tests pin that shape so it cannot widen unnoticed.
Will search keep working for anon callers?
The edge route in pages/api/vector-search.ts uses the service role key, which bypasses RLS, so the deployed search is untouched. What changes is what a leaked anon key could reach: function execution, not table reads.
What exactly do the pgTAP tests assert?
Three things: anon executes match_page_sections and gets rows back, select on nods_page and nods_page_section as anon returns zero rows, and anon inserts are rejected.
Does the agent run against my production project?
No. It runs supabase db test against the local CLI database configured in supabase/config.toml, Postgres 15. Applying the migration to a hosted project is a separate, deliberate supabase db push.
Can I scope the policies differently?
Yes, in the issue text. Which roles get which path through which function is the spec; a new run rewrites the migration and its tests to match.