Skip to content

Commit 0e3eab5

Browse files
committed
refactor: use Supabase service role key for worker authentication (#472)
# Use Supabase Service Role Key for Worker Authentication This PR simplifies the authentication mechanism for workers by leveraging the `SUPABASE_SERVICE_ROLE_KEY` that's automatically available in Edge Functions, eliminating the need for a separate `PGFLOW_SECRET_KEY`. Changes: - Workers now authenticate with the Control Plane using the Supabase service role key - Removed the `secretKey` option from `ControlPlaneOptions` interface - Updated the `verifyAuth` function to check against `SUPABASE_SERVICE_ROLE_KEY` environment variable - Modified tests to properly set and clean up the environment variable during testing - Added a test case for when the service role key is not set in the environment This change reduces configuration overhead as both Control Plane and Worker Edge Functions automatically have access to this key via `Deno.env`.
1 parent befd2d5 commit 0e3eab5

3 files changed

Lines changed: 277 additions & 230 deletions

File tree

PLAN.md

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,25 @@
3030

3131
## Authentication
3232

33-
Workers authenticate with ControlPlane using a dedicated secret key:
33+
Workers authenticate with ControlPlane using the Supabase service role key (zero-config):
3434

3535
```
36-
Env var: PGFLOW_SECRET_KEY
37-
Header: apikey: <secret_key>
36+
Env var: SUPABASE_SERVICE_ROLE_KEY (automatically available in Edge Functions)
37+
Header: apikey: <service_role_key>
3838
```
3939

4040
**Setup:**
41-
1. Users generate a secret key in Supabase dashboard (Supabase Secrets)
42-
2. Set `PGFLOW_SECRET_KEY` env var for both ControlPlane and Worker edge functions
43-
3. Workers include `apikey` header in compilation requests
44-
4. ControlPlane verifies `apikey` header matches `PGFLOW_SECRET_KEY` env var
41+
- No setup required - both ControlPlane and Worker Edge Functions automatically have access to `SUPABASE_SERVICE_ROLE_KEY` via `Deno.env`
42+
- Workers include `apikey` header in compilation requests
43+
- ControlPlane verifies `apikey` header matches `SUPABASE_SERVICE_ROLE_KEY` env var
4544

4645
**ControlPlane Verification:**
4746
```typescript
4847
function verifyAuth(request: Request): boolean {
48+
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
49+
if (!serviceRoleKey) return false; // Not configured - reject all
4950
const apikey = request.headers.get('apikey');
50-
const secretKey = Deno.env.get('PGFLOW_SECRET_KEY');
51-
if (!secretKey) return false; // Not configured - reject all
52-
return apikey === secretKey;
51+
return apikey === serviceRoleKey;
5352
}
5453
```
5554

@@ -66,7 +65,7 @@ Worker.start(MyFlow)
6665
6766
└── POST /flows/:slug/ensure-compiled
6867
│ Body: { shape: workerShape, mode: 'development' | 'production' }
69-
│ Headers: { apikey: PGFLOW_SECRET_KEY }
68+
│ Headers: { apikey: SUPABASE_SERVICE_ROLE_KEY }
7069
7170
└── ControlPlane (Layer 1: Deployment Validation)
7271
@@ -119,7 +118,7 @@ Worker.start(MyFlow)
119118

120119
```
121120
POST /flows/:slug/ensure-compiled
122-
Headers: { apikey: PGFLOW_SECRET_KEY }
121+
Headers: { apikey: SUPABASE_SERVICE_ROLE_KEY }
123122
Body: {
124123
shape: FlowShape,
125124
mode: 'development' | 'production'
@@ -718,7 +717,7 @@ Test-Driven Development order - write tests FIRST, then implement:
718717
### Phase 7: ControlPlane Endpoint (~0.5 day)
719718

720719
**Order within phase:**
721-
1. Add auth verification (check `PGFLOW_SECRET_KEY`)
720+
1. Add auth verification (check `SUPABASE_SERVICE_ROLE_KEY`)
722721
2. Add flow registry lookup (404 if not found)
723722
3. Add Layer 1: TypeScript comparison (409 if worker≠ControlPlane)
724723
4. Add Layer 2: SQL function call

pkgs/edge-worker/src/control-plane/server.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ export type SqlFunction = (strings: TemplateStringsArray, ...values: any[]) => P
4747
export interface ControlPlaneOptions {
4848
/** SQL function for database operations (required for ensure-compiled endpoint) */
4949
sql?: SqlFunction;
50-
/** Secret key for authentication (required for ensure-compiled endpoint) */
51-
secretKey?: string;
5250
}
5351

5452
/**
@@ -195,12 +193,13 @@ function jsonResponse(data: unknown, status: number): Response {
195193
}
196194

197195
/**
198-
* Verifies authentication using apikey header
196+
* Verifies authentication using apikey header against SUPABASE_SERVICE_ROLE_KEY env var
199197
*/
200-
function verifyAuth(request: Request, secretKey: string | undefined): boolean {
201-
if (!secretKey) return false;
198+
function verifyAuth(request: Request): boolean {
199+
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
200+
if (!serviceRoleKey) return false;
202201
const apikey = request.headers.get('apikey');
203-
return apikey === secretKey;
202+
return apikey === serviceRoleKey;
204203
}
205204

206205
/**
@@ -249,7 +248,7 @@ async function handleEnsureCompiled(
249248
}
250249

251250
// Verify authentication
252-
if (!verifyAuth(request, options.secretKey)) {
251+
if (!verifyAuth(request)) {
253252
return jsonResponse(
254253
{
255254
error: 'Unauthorized',

0 commit comments

Comments
 (0)