Skip to content

ENG-925 Upgrade supabase JWT keys#752

Merged
maparent merged 9 commits intomainfrom
eng-925-upgrade-supabase-jwt-keys
Feb 14, 2026
Merged

ENG-925 Upgrade supabase JWT keys#752
maparent merged 9 commits intomainfrom
eng-925-upgrade-supabase-jwt-keys

Conversation

@maparent
Copy link
Collaborator

@maparent maparent commented Feb 6, 2026

https://linear.app/discourse-graphs/issue/ENG-925/upgrade-supabase-jwt-keys

Status: This is now functional. We have to decide when to do it.
It is not urgent, but the work was done, and is worth using, since it is where supabase wants us to go.

The upsides are better key management and revocation.
The downside is that, when we change the keys, we have to change the function secrets. Supabase claims this may be automated someday.

https://github.com/supabase/supabase/blob/037e5f90a5689c3d847bd2adf9c8ec3956a0e7a0/apps/docs/content/guides/functions/auth.mdx


Open with Devin

@linear
Copy link

linear bot commented Feb 6, 2026

@supabase
Copy link

supabase bot commented Feb 6, 2026

Updates to Preview Branch (eng-925-upgrade-supabase-jwt-keys) ↗︎

Deployments Status Updated
Database Sat, 14 Feb 2026 00:47:53 UTC
Services Sat, 14 Feb 2026 00:47:53 UTC
APIs Sat, 14 Feb 2026 00:47:53 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Sat, 14 Feb 2026 00:47:53 UTC
Migrations Sat, 14 Feb 2026 00:47:54 UTC
Seeding Sat, 14 Feb 2026 00:47:54 UTC
Edge Functions Sat, 14 Feb 2026 00:47:56 UTC

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

View 5 additional findings in Devin Review.

Open in Devin Review

export const getVariant = () => {
const processHasVars =
!!process.env["SUPABASE_URL"] && !!process.env["SUPABASE_ANON_KEY"];
!!process.env["SUPABASE_URL"] && !!process.env["SUPABASE_PUBLISHABLE_KEY"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Local env generation produces SUPABASE_ANON_KEY but code expects SUPABASE_PUBLISHABLE_KEY

The createEnv.mts script generates local environment files by running supabase status -o env and prefixing variables with SUPABASE_. Supabase outputs ANON_KEY, which becomes SUPABASE_ANON_KEY. However, the PR changed all code to expect SUPABASE_PUBLISHABLE_KEY instead.

Root Cause

In packages/database/scripts/createEnv.mts:37-45, the script transforms supabase output:

const prefixed = stdout
  .split("\n")
  .map((line) =>
    /^API_URL=/.test(line)
      ? `SUPABASE_URL=${line.substring(8)}`
      : `SUPABASE_${line}`,
  )

This produces SUPABASE_ANON_KEY from supabase's ANON_KEY output, but packages/database/src/dbDotEnv.mjs:20 and packages/database/src/dbDotEnv.mjs:77 now check for SUPABASE_PUBLISHABLE_KEY.

Impact: Local development will fail because SUPABASE_PUBLISHABLE_KEY will be undefined, causing the database connection to fail with "Missing required Supabase environment variables".

Prompt for agents
Update packages/database/scripts/createEnv.mts to transform ANON_KEY to SUPABASE_PUBLISHABLE_KEY instead of SUPABASE_ANON_KEY. In the makeLocalEnv function around line 37-45, add a transformation that converts ANON_KEY= to PUBLISHABLE_KEY= before prefixing with SUPABASE_, similar to how API_URL is handled. The transformation should result in SUPABASE_PUBLISHABLE_KEY being written to the .env.local file.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supabase outputs both the ANON_KEY and the PUBLISHABLE_KEY, once the latter have been set up.

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

@maparent maparent force-pushed the eng-925-upgrade-supabase-jwt-keys branch 2 times, most recently from 99e4c4b to bc00faa Compare February 7, 2026 18:11
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

🐛 1 issue in files not directly in the diff

🐛 /api/supabase/env route still returns SUPABASE_ANON_KEY but consumers expect SUPABASE_PUBLISHABLE_KEY (apps/website/app/api/supabase/env/route.ts:9-14)

The env API route was not migrated to the new key name, breaking the Roam production build pipeline.

Root Cause

apps/website/app/api/supabase/env/route.ts:9-14 still destructures and returns SUPABASE_ANON_KEY from process.env. This endpoint is called during the Roam build (packages/database/scripts/createEnv.mts:131), which fetches from https://discoursegraphs.com/api/supabase/env and writes the result to .env. The .env file will therefore contain SUPABASE_ANON_KEY=....

When envContents() at packages/database/src/dbDotEnv.mjs:82-83 reads and parses this file, the result will have SUPABASE_ANON_KEY as a key. But the compile scripts (apps/roam/scripts/compile.ts:165, apps/obsidian/scripts/compile.ts:126) now access dbEnv.SUPABASE_PUBLISHABLE_KEY, which will be undefined.

Impact: The Roam and Obsidian production builds (when triggered via ROAM_BUILD_SCRIPT) will embed null for the Supabase key, breaking all Supabase client initialization in the built extensions.

View 9 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 11 additional findings in Devin Review.

Open in Devin Review

@maparent maparent force-pushed the eng-925-upgrade-supabase-jwt-keys branch 2 times, most recently from f02939d to 7a7feac Compare February 12, 2026 19:56
@maparent maparent requested a review from mdroidian February 12, 2026 22:23
@maparent maparent force-pushed the eng-925-upgrade-supabase-jwt-keys branch from 631abef to 6341a73 Compare February 14, 2026 00:45
@maparent maparent merged commit 38fd0c1 into main Feb 14, 2026
9 of 10 checks passed
@maparent maparent deleted the eng-925-upgrade-supabase-jwt-keys branch February 14, 2026 00:50
Comment on lines +234 to +235
const supabaseAnonClient: DGSupabaseClient = createClient(
url, token, { global: { headers: { Authorization: authHeader } } });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical Bug: The createClient call is passing the user's JWT token as the second parameter, but this parameter expects the Supabase anon/publishable key, not a user token. This will fail to create a valid Supabase client.

The token is already being passed in the Authorization header via options. The second parameter should be the SB_PUBLISHABLE_KEY from environment variables.

const anonKey = Deno.env.get("SB_PUBLISHABLE_KEY");
if (!anonKey) {
  return Response.json(
    { msg: 'Missing SB_PUBLISHABLE_KEY' },
    { status: 500 }
  )
}
const supabaseAnonClient: DGSupabaseClient = createClient(
  url, anonKey, { global: { headers: { Authorization: authHeader } } });
Suggested change
const supabaseAnonClient: DGSupabaseClient = createClient(
url, token, { global: { headers: { Authorization: authHeader } } });
const anonKey = Deno.env.get("SB_PUBLISHABLE_KEY");
if (!anonKey) {
return Response.json(
{ msg: 'Missing SB_PUBLISHABLE_KEY' },
{ status: 500 }
)
}
const supabaseAnonClient: DGSupabaseClient = createClient(
url, anonKey, { global: { headers: { Authorization: authHeader } } });

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants