@cerefox/memory 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,117 @@
1
+ # Google Cloud Run Deployment
2
+
3
+ Deploy the Cerefox web UI to Google Cloud Run for a lightweight, serverless hosting option. This guide uses Supabase (free tier) for the database.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - Google Cloud account with billing enabled
10
+ - `gcloud` CLI installed and authenticated (`gcloud auth login`)
11
+ - Supabase project set up (see `setup-supabase.md`)
12
+ - Docker installed locally
13
+
14
+ ---
15
+
16
+ ## Step 1 — Set up environment variables
17
+
18
+ ```bash
19
+ export PROJECT_ID=your-gcp-project-id
20
+ export REGION=us-central1
21
+ export SERVICE_NAME=cerefox
22
+ export IMAGE=gcr.io/$PROJECT_ID/$SERVICE_NAME
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Step 2 — Build and push the Docker image
28
+
29
+ ```bash
30
+ # Authenticate Docker to GCR
31
+ gcloud auth configure-docker
32
+
33
+ # Build and push
34
+ docker build -t $IMAGE .
35
+ docker push $IMAGE
36
+ ```
37
+
38
+ Or use Cloud Build for fully cloud-side building:
39
+
40
+ ```bash
41
+ gcloud builds submit --tag $IMAGE .
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Step 3 — Deploy to Cloud Run
47
+
48
+ ```bash
49
+ gcloud run deploy $SERVICE_NAME \
50
+ --image $IMAGE \
51
+ --region $REGION \
52
+ --platform managed \
53
+ --allow-unauthenticated \
54
+ --port 8000 \
55
+ --memory 512Mi \
56
+ --cpu 1 \
57
+ --set-env-vars \
58
+ CEREFOX_SUPABASE_URL=https://YOUR-REF.supabase.co,\
59
+ CEREFOX_SUPABASE_KEY=YOUR-SERVICE-ROLE-KEY,\
60
+ OPENAI_API_KEY=YOUR-OPENAI-KEY,\
61
+ CEREFOX_MAX_RESPONSE_BYTES=200000
62
+ ```
63
+
64
+ **Memory**: Cerefox uses cloud embeddings (OpenAI API) — no local model is loaded. `--memory 512Mi` is sufficient for the web server alone.
65
+
66
+ **CPU**: `--cpu 1` is sufficient for personal use. Scale up for concurrent users.
67
+
68
+ ---
69
+
70
+ ## Step 4 — Verify the deployment
71
+
72
+ ```bash
73
+ gcloud run services describe $SERVICE_NAME --region $REGION --format="value(status.url)"
74
+ ```
75
+
76
+ Open the printed URL — the Cerefox dashboard should load.
77
+
78
+ ---
79
+
80
+ ## Updating the deployment
81
+
82
+ After making code changes:
83
+
84
+ ```bash
85
+ docker build -t $IMAGE .
86
+ docker push $IMAGE
87
+ gcloud run deploy $SERVICE_NAME --image $IMAGE --region $REGION --platform managed
88
+ ```
89
+
90
+ Cloud Run performs a zero-downtime rolling update.
91
+
92
+ ---
93
+
94
+ ## Cost
95
+
96
+ For a typical single-user personal knowledge base, Cloud Run comfortably fits within its
97
+ always-free tier limits. The main variable expense is OpenAI embedding calls, shared with
98
+ all other deployment options. See `docs/guides/operational-cost.md` for a full breakdown.
99
+
100
+ ---
101
+
102
+ ## Securing access
103
+
104
+ By default `--allow-unauthenticated` makes the URL public. To restrict access:
105
+
106
+ ### Option 1 — Cloud Run IAM
107
+
108
+ Remove `--allow-unauthenticated` and use `gcloud run services add-iam-policy-binding` to add specific Google accounts.
109
+
110
+ ### Option 2 — Cloud Run proxy
111
+
112
+ Use Identity-Aware Proxy (IAP) in front of Cloud Run for Google SSO.
113
+
114
+ ### Option 3 — Add HTTP basic auth
115
+
116
+ In `src/cerefox/api/app.py`, add a middleware that checks `Authorization: Basic ...` headers. Use `CEREFOX_BASIC_AUTH_USER` / `CEREFOX_BASIC_AUTH_PASSWORD` env vars.
117
+
@@ -0,0 +1,178 @@
1
+ # Local Setup Guide
2
+
3
+ Run the Cerefox web server and database on your own machine using Docker for Postgres+pgvector. Embeddings use the OpenAI API — an `OPENAI_API_KEY` is required even for local setups.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - Docker and Docker Compose
10
+ - Python 3.11+ with `uv` (`pip install uv`)
11
+ - An OpenAI API key (for embeddings — [platform.openai.com/api-keys](https://platform.openai.com/api-keys))
12
+
13
+ ---
14
+
15
+ ## Step 1 — Clone and install
16
+
17
+ ```bash
18
+ git clone https://github.com/fstamatelopoulos/cerefox.git
19
+ cd cerefox
20
+ uv sync
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Step 2 — Start Postgres with pgvector
26
+
27
+ The included `docker-compose.yml` spins up a Postgres 16 instance with the pgvector extension pre-installed:
28
+
29
+ ```bash
30
+ docker compose up -d postgres
31
+ ```
32
+
33
+ Default connection details (overridable in `.env`):
34
+
35
+ | Setting | Default |
36
+ |---------|---------|
37
+ | Host | `localhost` |
38
+ | Port | `5432` |
39
+ | User | `cerefox` |
40
+ | Password | `cerefox` |
41
+ | Database | `cerefox` |
42
+
43
+ ---
44
+
45
+ ## Step 3 — Create a `.env` file
46
+
47
+ ```bash
48
+ cp .env.example .env
49
+ ```
50
+
51
+ Edit `.env` for local Docker:
52
+
53
+ ```env
54
+ # Local Postgres (Docker)
55
+ CEREFOX_DATABASE_URL=postgresql://cerefox:cerefox@localhost:5432/cerefox
56
+
57
+ # For local-only use, Supabase keys are not required.
58
+ # The web UI and CLI will work without them if you skip the Supabase MCP integration.
59
+ CEREFOX_SUPABASE_URL=
60
+ CEREFOX_SUPABASE_KEY=
61
+
62
+ # OpenAI API key for embeddings (text-embedding-3-small)
63
+ OPENAI_API_KEY=sk-...
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Step 4 — Deploy the schema
69
+
70
+ ```bash
71
+ python scripts/db_deploy.py
72
+ ```
73
+
74
+ This creates all tables, indexes, and RPC functions. Run with `--dry-run` to preview SQL without executing.
75
+
76
+ To start fresh:
77
+
78
+ ```bash
79
+ python scripts/db_deploy.py --reset # drops all cerefox_ tables first
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Step 5 — Verify the setup
85
+
86
+ ```bash
87
+ python scripts/db_status.py
88
+ ```
89
+
90
+ You should see all tables (cerefox_documents, cerefox_chunks, cerefox_projects) and RPC functions listed as ✓.
91
+
92
+ ---
93
+
94
+ ## Step 6 — Ingest your first document
95
+
96
+ ```bash
97
+ # Ingest a markdown file
98
+ cerefox ingest my-notes.md --project-name "personal"
99
+
100
+ # Or paste content from stdin
101
+ echo "# Quick Note\n\nThis is a quick note." | cerefox ingest --paste --title "Quick Note"
102
+ ```
103
+
104
+ Each ingest calls the OpenAI embedding API once per batch of chunks (fast, typically under a second).
105
+
106
+ ---
107
+
108
+ ## Step 7 — Start the web UI
109
+
110
+ ```bash
111
+ cerefox web
112
+ ```
113
+
114
+ Open [http://localhost:8000](http://localhost:8000) in your browser.
115
+
116
+ For development with auto-reload:
117
+
118
+ ```bash
119
+ cerefox web --reload
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Step 8 — Search from the CLI
125
+
126
+ ```bash
127
+ # Hybrid search (recommended)
128
+ cerefox search "what did I write about project planning?"
129
+
130
+ # Keyword-only search
131
+ cerefox search "meeting notes" --mode fts
132
+
133
+ # Semantic search
134
+ cerefox search "ideas about creativity" --mode semantic
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Running everything at once
140
+
141
+ The `docker-compose.yml` also includes a `cerefox` service that runs the web UI:
142
+
143
+ ```bash
144
+ docker compose up -d
145
+ ```
146
+
147
+ Web UI will be at [http://localhost:8000](http://localhost:8000).
148
+
149
+ ---
150
+
151
+ ## Stopping services
152
+
153
+ ```bash
154
+ docker compose down # stop, keep data
155
+ docker compose down -v # stop and delete database volume
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Updating the schema
161
+
162
+ When a new version of Cerefox introduces schema changes, run:
163
+
164
+ ```bash
165
+ python scripts/db_migrate.py
166
+ ```
167
+
168
+ This applies incremental migrations without losing data. Always back up first (see `ops-scripts.md`).
169
+
170
+ ---
171
+
172
+ ## Troubleshooting
173
+
174
+ **pgvector extension not found**
175
+ Make sure you're using the `pgvector/pgvector:pg16` Docker image (included in `docker-compose.yml`). Raw Postgres images do not include pgvector.
176
+
177
+ **"Supabase is not configured" error**
178
+ The CLI and web UI show this error if `CEREFOX_SUPABASE_URL` / `CEREFOX_SUPABASE_KEY` are empty. For local Docker setups, the app uses the direct Postgres URL (`CEREFOX_DATABASE_URL`) for schema deployment but the Supabase client for queries. Set up a local Supabase instance or use the hosted free tier (see `setup-supabase.md`).
@@ -0,0 +1,370 @@
1
+ # Setting Up Cerefox with Supabase
2
+
3
+ This guide walks you from a blank Supabase project to a fully deployed Cerefox schema, ready to ingest documents and serve AI agents via MCP.
4
+
5
+ **Time required**: ~15 minutes
6
+
7
+ ---
8
+
9
+ ## Prerequisites
10
+
11
+ - [uv](https://docs.astral.sh/uv/getting-started/installation/) installed
12
+ - A Supabase account (free tier is enough): [supabase.com](https://supabase.com)
13
+ - Python 3.11 or higher
14
+
15
+ ---
16
+
17
+ ## Step 1 — Create a Supabase Project
18
+
19
+ 1. Go to [app.supabase.com](https://app.supabase.com) and sign in
20
+ 2. Click **New project**
21
+ 3. Choose a name (e.g. `cerefox`), set a strong database password, pick a region close to you
22
+ 4. Click **Create new project** and wait ~2 minutes for it to provision
23
+
24
+ ---
25
+
26
+ ## Step 2 — Enable the pgvector Extension
27
+
28
+ Supabase includes pgvector but you need to activate it:
29
+
30
+ 1. In your project dashboard, go to **Database → Extensions**
31
+ 2. Search for `vector` and enable it
32
+
33
+ The deploy script also runs `CREATE EXTENSION IF NOT EXISTS vector` automatically, but enabling it in the UI first prevents permission issues.
34
+
35
+ ---
36
+
37
+ ## Step 3 — Collect Your Credentials
38
+
39
+ You need three values from Supabase: a URL, an API key, and a direct Postgres connection string. The API-key panel and the connection-string panel both went through significant changes in 2026 — read the two reference sections below for the up-to-date guidance.
40
+
41
+ ### 3a. API URL
42
+ - **Project Settings → API → Project URL** → `CEREFOX_SUPABASE_URL`
43
+
44
+ ### 3b. API key — `CEREFOX_SUPABASE_KEY`
45
+
46
+ See the **[Supabase API keys (2026)](#supabase-api-keys-2026)** section near the end of this guide for the full picture. The short version:
47
+
48
+ - For `CEREFOX_SUPABASE_KEY` (this guide, Python web app, CLI): use the new **secret key** (`sb_secret_…`) from **Project Settings → API Keys → Secret key**. The legacy `service_role` JWT also still works during the transition.
49
+ - For `CEREFOX_SUPABASE_ANON_KEY` (only if you'll use Edge Functions / MCP / GPT Actions; not needed for this guide's deployment step): you must use the **legacy anon JWT** (`eyJ…`). The new `sb_publishable_…` key fails at the Edge Function gateway. See the reference section for why.
50
+
51
+ Either way: keep this key secret — it bypasses Row Level Security and grants full database access.
52
+
53
+ ### 3c. Direct database URL — `CEREFOX_DATABASE_URL`
54
+
55
+ This is used by `db_deploy.py`, `db_migrate.py`, and `db_status.py`. See the **[Connection pooling in 2026](#connection-pooling-2026)** reference section near the end of this guide for context. The short version:
56
+
57
+ 1. Open **Project Settings → Database → Connection pooling** (not the "Connect" dialog — that one usually omits the Session Pooler in the new UI).
58
+ 2. Copy the **Session Pooler** URI (host ends in `.pooler.supabase.com`, port `5432`).
59
+ 3. Confirm the username has the form `postgres.<project-ref>` — without that suffix you'll get "Tenant or user not found".
60
+ 4. Append `?sslmode=require` to enforce TLS explicitly.
61
+
62
+ If you only see Direct Connection and Transaction Pooler in your dashboard, take the Transaction Pooler URI and change `:6543` → `:5432`. That gives you the Session Pooler. **Do not use port 6543** — Transaction Pooler does not support DDL and `db_deploy.py` will fail mid-schema.
63
+
64
+ The Direct Connection (`db.<project-ref>.supabase.co:5432`) is IPv6-only on the free tier and unusable on most home/office networks. The dashboard now warns about this directly.
65
+
66
+ ---
67
+
68
+ ## Step 4 — Configure Your Environment
69
+
70
+ ```bash
71
+ # In the cerefox project root:
72
+ cp .env.example .env
73
+ ```
74
+
75
+ Edit `.env` and fill in your values. A minimal working configuration looks like:
76
+
77
+ ```bash
78
+ CEREFOX_SUPABASE_URL=https://your-project-ref.supabase.co
79
+ CEREFOX_SUPABASE_KEY=sb_secret_...your-secret-key...
80
+ CEREFOX_DATABASE_URL=postgresql://postgres.yourref:yourpassword@aws-N-region.pooler.supabase.com:5432/postgres?sslmode=require
81
+ # CEREFOX_SUPABASE_ANON_KEY only needed if you'll deploy Edge Functions (Step 8)
82
+ # Must be the legacy anon JWT, NOT sb_publishable_... — see "Supabase API keys (2026)" below
83
+ # CEREFOX_SUPABASE_ANON_KEY=eyJ...your-legacy-anon-jwt...
84
+ ```
85
+
86
+ Leave all other settings at their defaults for now.
87
+
88
+ ---
89
+
90
+ ## Step 5 — Install Dependencies
91
+
92
+ ```bash
93
+ uv sync
94
+ ```
95
+
96
+ This installs all Python dependencies defined in `pyproject.toml`, including `supabase`, `psycopg2-binary`, and `pydantic-settings`.
97
+
98
+ ---
99
+
100
+ ## Step 6 — Deploy the Schema
101
+
102
+ ```bash
103
+ # Preview what will happen (no changes made):
104
+ python scripts/db_deploy.py --dry-run
105
+
106
+ # Apply the schema:
107
+ python scripts/db_deploy.py
108
+ ```
109
+
110
+ Expected output:
111
+ ```
112
+ ╔══════════════════════════════════════╗
113
+ ║ Cerefox DB Deploy ║
114
+ ╚══════════════════════════════════════╝
115
+
116
+ Connecting to database...
117
+
118
+ ▶ Enable extensions (uuid-ossp, vector/pgvector)...
119
+ ✓ Done
120
+
121
+ ▶ Apply schema (tables, indexes, triggers)...
122
+ ✓ Done
123
+
124
+ ▶ Apply RPCs (search functions)...
125
+ ✓ Done
126
+
127
+ ──────────────────────────────────────────
128
+ ✓ Deployment complete. 3 steps applied.
129
+
130
+ Next step: verify the schema with:
131
+ python scripts/db_status.py
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Step 7 — Verify the Schema
137
+
138
+ ```bash
139
+ python scripts/db_status.py
140
+ ```
141
+
142
+ Expected output:
143
+ ```
144
+ ╔══════════════════════════════════════╗
145
+ ║ Cerefox DB Status ║
146
+ ╚══════════════════════════════════════╝
147
+
148
+ Extensions:
149
+ ✓ uuid-ossp
150
+ ✓ vector
151
+
152
+ Tables:
153
+ ✓ cerefox_projects
154
+ ✓ cerefox_documents
155
+ ✓ cerefox_chunks
156
+ ✓ cerefox_migrations
157
+
158
+ Functions / RPCs:
159
+ ✓ cerefox_set_updated_at()
160
+ ✓ cerefox_hybrid_search()
161
+ ✓ cerefox_fts_search()
162
+ ✓ cerefox_semantic_search()
163
+ ✓ cerefox_reconstruct_doc()
164
+ ✓ cerefox_save_note()
165
+ ✓ cerefox_search_docs()
166
+ ✓ cerefox_context_expand()
167
+
168
+ Indexes:
169
+ ✓ idx_cerefox_chunks_fts
170
+ ✓ idx_cerefox_chunks_emb_primary
171
+ ✓ idx_cerefox_chunks_emb_upgrade
172
+ ✓ idx_cerefox_chunks_document
173
+ ✓ idx_cerefox_docs_metadata
174
+ ✓ idx_cerefox_docs_project
175
+
176
+ Row counts:
177
+ ℹ cerefox_projects: 0 rows
178
+ ℹ cerefox_documents: 0 rows
179
+ ℹ cerefox_chunks: 0 rows
180
+
181
+ ──────────────────────────────────────────
182
+ ✓ All checks passed. Schema looks healthy.
183
+ ```
184
+
185
+ All checks should show ✓. If any show ✗, re-run `python scripts/db_deploy.py`.
186
+
187
+ ---
188
+
189
+ ## Step 8 — Deploy Edge Functions
190
+
191
+ The Edge Functions run server-side on Supabase. `cerefox-search` and `cerefox-ingest` handle
192
+ embedding for agents; `cerefox-mcp` wraps them as a remote MCP endpoint (recommended for
193
+ Claude Code, Cursor, and Claude Desktop). Deploy using the Supabase CLI via `npx` — no
194
+ separate install needed, just Node.js.
195
+
196
+ **First time only — authenticate and link your project:**
197
+
198
+ ```bash
199
+ npx supabase login # opens a browser tab; click "Confirm" to generate an access token
200
+ npx supabase link # prompts for your project ref (the ID in your Supabase dashboard URL)
201
+ ```
202
+
203
+ Your project ref is in the Supabase dashboard URL:
204
+ `https://supabase.com/dashboard/project/<project-ref>`
205
+
206
+ **Deploy all three functions** (from the cerefox project root):
207
+
208
+ ```bash
209
+ npx supabase functions deploy cerefox-ingest
210
+ npx supabase functions deploy cerefox-search
211
+ npx supabase functions deploy cerefox-mcp
212
+ ```
213
+
214
+ Expected output for each:
215
+ ```
216
+ Bundling Function: cerefox-ingest
217
+ Deploying Function: cerefox-ingest (script size: ~880kB)
218
+ Deployed Functions on project <your-project-ref>: cerefox-ingest
219
+ ```
220
+
221
+ You can verify in the Supabase Dashboard → **Edge Functions** — all three functions should
222
+ appear with a green "Active" status.
223
+
224
+ > **Re-deploying after updates**: run the same `npx supabase functions deploy` commands
225
+ > again from the project root. `npx supabase login` and `npx supabase link` only need to be
226
+ > run once per machine.
227
+
228
+ ---
229
+
230
+ ## Step 9 — Run the Tests
231
+
232
+ Confirm everything is wired up correctly:
233
+
234
+ ```bash
235
+ uv run pytest
236
+ ```
237
+
238
+ These are unit tests only (no real database connection needed). You should see all tests pass.
239
+
240
+ To also run the integration tests against your live Supabase instance:
241
+ ```bash
242
+ uv run pytest -m integration
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Step 11 — Connect an AI agent (optional)
248
+
249
+ Cerefox ships a built-in MCP server that gives desktop agents named tools
250
+ (`cerefox_search`, `cerefox_ingest`) with full hybrid search.
251
+
252
+ **For Claude Desktop / ChatGPT Desktop / Cursor** — add to the client's MCP config:
253
+ ```json
254
+ {
255
+ "mcpServers": {
256
+ "cerefox": {
257
+ "command": "uv",
258
+ "args": ["--directory", "/path/to/cerefox", "run", "cerefox", "mcp"]
259
+ }
260
+ }
261
+ }
262
+ ```
263
+
264
+ **For cloud Claude.ai** — connect to the Supabase remote MCP (FTS keyword search only):
265
+ 1. In Supabase Dashboard → Project Settings → Integrations → MCP, get your project ref
266
+ 2. In Claude.ai Settings → Integrations, add `https://mcp.supabase.com/sse?project_ref=<ref>`
267
+
268
+ **For cloud ChatGPT** — create a Custom GPT with GPT Actions pointing at the Edge Functions.
269
+
270
+ See `docs/guides/connect-agents.md` for the complete guide including system prompts,
271
+ architecture explanation, and ChatGPT GPT Actions setup.
272
+
273
+ ---
274
+
275
+ ## Troubleshooting
276
+
277
+ ### "could not connect to server"
278
+ - Check that `CEREFOX_DATABASE_URL` is correct and the password doesn't contain special characters that need URL-encoding
279
+ - Try pasting the URL directly into `psql` to verify it works
280
+
281
+ ### "extension 'vector' does not exist"
282
+ - Go to Supabase Dashboard → Database → Extensions → enable `vector`
283
+ - Then re-run `python scripts/db_deploy.py`
284
+
285
+ ### "permission denied for table"
286
+ - Make sure `CEREFOX_SUPABASE_KEY` is your secret key (`sb_secret_…`) or legacy `service_role` JWT — not the publishable / anon key. See [Supabase API keys (2026)](#supabase-api-keys-2026) below.
287
+
288
+ ### Schema already exists (re-deploying)
289
+ - All schema objects use `CREATE ... IF NOT EXISTS` / `CREATE OR REPLACE`, so re-running is safe
290
+ - To start completely fresh: `python scripts/db_deploy.py --reset` (⚠️ deletes all data)
291
+
292
+ ---
293
+
294
+ ## Supabase API keys (2026) <a id="supabase-api-keys-2026"></a>
295
+
296
+ In 2026 Supabase rolled out a new API key system. The dashboard now shows two key types side by side, and the migration is **asymmetric** — one half is fully migrated, the other is not. Cerefox needs values from both halves.
297
+
298
+ ### The two key families
299
+
300
+ | Family | What you'll see in the dashboard | Use it for |
301
+ |---|---|---|
302
+ | **New (recommended)** | "Publishable key" (`sb_publishable_…`) and "Secret key" (`sb_secret_…`) | `CEREFOX_SUPABASE_KEY` — works end-to-end through the Data API. |
303
+ | **Legacy** | "anon" and "service_role" JWTs (`eyJ…`), filed under a "Legacy" section | `CEREFOX_SUPABASE_ANON_KEY` — **still required** for any Edge Function call (MCP, GPT Actions, e2e tests, direct curl). |
304
+
305
+ ### What goes where in `.env`
306
+
307
+ | Variable | Recommended value | Why |
308
+ |---|---|---|
309
+ | `CEREFOX_SUPABASE_KEY` | New **secret key** (`sb_secret_…`). Legacy `service_role` JWT also works. | Used by `db/client.py` to reach the Data API (PostgREST). Both formats are accepted by the gateway. |
310
+ | `CEREFOX_SUPABASE_ANON_KEY` | **Legacy anon JWT** (`eyJ…`). | Used as the `Authorization: Bearer …` header for Edge Function calls. The Supabase Edge Function gateway still validates this token as a JWT — it parses `header.payload.signature` and rejects non-JWT keys with `UNAUTHORIZED_INVALID_JWT_FORMAT`. The new `sb_publishable_…` key is not a JWT and fails. |
311
+
312
+ ### Why we cannot just use the new keys everywhere
313
+
314
+ The Data API gateway was migrated in 2026 to accept both the new and legacy key formats. The Edge Function gateway was not. A Supabase team member [confirmed this](https://github.com/orgs/supabase/discussions/41834): the only way to call Edge Functions with the new keys today is to deploy each function with `verify_jwt = false` and validate the key inside the function. Cerefox is not yet doing that (a future migration; see Decision Log 2026 Q2 for context and triggers).
315
+
316
+ ### Is the legacy key going away?
317
+
318
+ Not yet. The Supabase docs explicitly state: *"You can still use old anon and service-role API keys after enabling the publishable and secret keys."* The "Legacy" label in the dashboard suggests deprecation, but **no end-of-life date has been published** as of May 2026. When Supabase announces one, Cerefox will migrate.
319
+
320
+ ### Sources
321
+
322
+ - [Edge Function returning "JWT is invalid" after migrating to 2026 API Keys — supabase/discussions#41834](https://github.com/orgs/supabase/discussions/41834)
323
+ - [Understanding API keys — Supabase Docs](https://supabase.com/docs/guides/api/api-keys)
324
+ - [Securing Edge Functions — Supabase Docs](https://supabase.com/docs/guides/functions/auth)
325
+
326
+ ---
327
+
328
+ ## Connection pooling in 2026 <a id="connection-pooling-2026"></a>
329
+
330
+ Supabase's "Connect" dialog was redesigned in 2026 and the **Session Pooler** is no longer a first-class tab in many projects. The other two surfaces (Direct Connection and Transaction Pooler) are present but neither works for Cerefox's deployment scripts. Here's the full picture.
331
+
332
+ ### The three Postgres connection types
333
+
334
+ | Type | Host / port | DDL support | IPv4 compatible? | Use for Cerefox? |
335
+ |---|---|---|---|---|
336
+ | **Direct Connection** | `db.<project-ref>.supabase.co:5432` | ✓ | **IPv6 only on free tier.** Dashboard warns about this directly. | No — most networks can't reach it. |
337
+ | **Transaction Pooler** | `aws-N-region.pooler.supabase.com:6543` (note port) | **✗ no DDL** | ✓ | No — `db_deploy.py` fails mid-schema. |
338
+ | **Session Pooler** | `aws-N-region.pooler.supabase.com:5432` | ✓ | ✓ | **Yes — use this.** |
339
+
340
+ The Transaction Pooler runs PgBouncer in transaction mode and does not maintain a session between statements, breaking DDL, prepared statements, `SET LOCAL`, and advisory locks. The Session Pooler is the same hostname on a different port and keeps a full session per connection.
341
+
342
+ ### Finding the Session Pooler URI
343
+
344
+ Two reliable paths in the current dashboard:
345
+
346
+ 1. **Project Settings → Database → Connection pooling.** The Session Pooler URI is listed here.
347
+ 2. **Quick shortcut**: take whatever Transaction Pooler URI the "Connect" dialog shows you and change `:6543` → `:5432`. Same host, same username, just session mode instead of transaction mode.
348
+
349
+ ### Required pieces of the connection string
350
+
351
+ - **Host**: `aws-N-region.pooler.supabase.com` (substituted by your project's region — e.g. `aws-1-us-east-1`).
352
+ - **Port**: `5432` — **never `6543`** for Cerefox.
353
+ - **Username**: `postgres.<project-ref>` — the `.<project-ref>` suffix is mandatory. Without it Supabase returns "Tenant or user not found".
354
+ - **Password**: the database password set when you created the project (or rotated under Project Settings → Database). URL-encode special characters (`@` → `%40`, etc.) or pick a URL-safe password to avoid the gotcha.
355
+ - **Query string**: append `?sslmode=require` to enforce TLS explicitly. Supabase enforces TLS server-side anyway; being explicit doesn't hurt.
356
+
357
+ Final shape:
358
+
359
+ ```
360
+ postgresql://postgres.<project-ref>:<password>@aws-N-<region>.pooler.supabase.com:5432/postgres?sslmode=require
361
+ ```
362
+
363
+ ### Common errors and what they mean
364
+
365
+ | Error | Likely cause |
366
+ |---|---|
367
+ | `Tenant or user not found` | Username is missing the `.<project-ref>` suffix. |
368
+ | `nodename nor servname provided` | You used the Direct Connection on an IPv4-only network. Switch to Session Pooler. |
369
+ | `cannot create function ... transaction mode does not support ...` (or similar mid-schema failure) | You used the Transaction Pooler (port 6543). Switch to Session Pooler (port 5432). |
370
+ | `password authentication failed` | Wrong password, or special characters not URL-encoded. Reset under Project Settings → Database. |