Skip to content
Merged
Show file tree
Hide file tree
Changes from 84 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
43c7ae6
feat(backend): support JWKS-based JWT validation and drop Supabase se…
ntindle Jun 10, 2026
39d47f3
feat(platform): replace Supabase auth with Better Auth embedded in th…
ntindle Jun 10, 2026
98d74b5
ci+docs(platform): provision plain Postgres in CI and update docs for…
ntindle Jun 10, 2026
24a7e78
chore: remove stray vitest cache committed from repo root
ntindle Jun 10, 2026
6a3645f
fix(frontend): keep Better Auth server code out of client bundles
ntindle Jun 10, 2026
3980bb0
fix(platform): address review findings on Better Auth migration
ntindle Jun 10, 2026
fbfc4cd
test(frontend): cover the Better Auth module (actions, config, email,…
ntindle Jun 10, 2026
2315e5f
fix(backend): auto-create marketplace Profile in get_or_create_user
ntindle Jun 10, 2026
0e34f2f
fix(backend): tolerate concurrent default-profile creation
ntindle Jun 10, 2026
e8980ed
fix(frontend): fail auth flows when production SMTP is unconfigured
ntindle Jun 10, 2026
f147790
fix(backend): upsert test-fixture profiles now that get_or_create_use…
ntindle Jun 10, 2026
6deb6ac
test(frontend): unit-cover auth flow actions and routes
ntindle Jun 10, 2026
498a3ae
fix(backend): distinguish username collisions from concurrent profile…
ntindle Jun 10, 2026
177e8f2
fix(frontend): roll back the auth session when post-login provisionin…
ntindle Jun 10, 2026
258ac54
test(frontend): cover rollbackSession
ntindle Jun 10, 2026
5d0c369
fix(frontend): enable Better Auth email change for the settings page
ntindle Jun 10, 2026
d0e6267
refactor(libs): drop dead Supabase module and unused dependencies
ntindle Jun 10, 2026
e52f1a2
docs(platform): align setup docs with the Better Auth stack
ntindle Jun 10, 2026
98230ee
merge: origin/dev into better-auth-migration
ntindle Jun 16, 2026
e4f92da
fix(libs): validate JWKS URL format and rekey the client on URL change
ntindle Jun 16, 2026
0ec3867
merge: origin/dev into better-auth-migration (catch up)
ntindle Jun 16, 2026
791ff21
feat(frontend): env-driven signup gating (allow-new-accounts + allowl…
ntindle Jun 18, 2026
fbd7b83
merge: origin/dev into better-auth-migration (catch up)
ntindle Jun 27, 2026
fa8abe3
merge: origin/dev into better-auth-migration (catch up)
ntindle Jul 2, 2026
4a09fde
fix(frontend): bump nodemailer 9.0.1 + vitest 4.1.9 to clear Snyk vulns
ntindle Jul 2, 2026
6a316c0
fix(frontend): revert vitest bump, keep nodemailer 9.0.1
ntindle Jul 2, 2026
06cfc0e
merge dev into better-auth-migration (resolve profile-creation + auth…
ntindle Jul 5, 2026
f53d8fa
fix(backend): drop duplicate TestGetOrCreateUserProfile brought in by…
ntindle Jul 5, 2026
c1bd2be
merge: origin/dev into better-auth-migration (catch up)
ntindle Jul 9, 2026
f1550db
fix(backend): align user.py profile provisioning with dev (de-dup merge)
ntindle Jul 9, 2026
c8724a6
fix(frontend): logout now clears __Secure- cookies over HTTPS
ntindle Jul 10, 2026
4131f1c
feat(platform): route Better Auth emails through the backend mailer
ntindle Jul 11, 2026
a773edb
refactor(platform): auth emails via JWKS service tokens, drop AUTH_EM…
ntindle Jul 11, 2026
7309eca
refactor(backend): forward auth emails to the notification service
ntindle Jul 11, 2026
32c90a8
Merge remote-tracking branch 'origin/dev' into better-auth-migration
ntindle Jul 11, 2026
bb12e72
fix(frontend): port merged tour-sidebar auth check to useAuth + sync …
ntindle Jul 11, 2026
b59eee1
Merge remote-tracking branch 'origin/dev' into better-auth-migration
ntindle Jul 14, 2026
a62e9f6
fix(backend): regenerate poetry.lock with poetry 2.2.1 to match CI
ntindle Jul 14, 2026
b9af56e
Merge remote-tracking branch 'origin/dev' into better-auth-migration
ntindle Jul 17, 2026
7d0e7ac
fix(frontend): port EmptySession helpers test off @supabase/supabase-js
ntindle Jul 17, 2026
bf998bd
ci(platform): fail e2e loudly when rest_server never becomes healthy
ntindle Jul 17, 2026
cf8292c
Merge remote-tracking branch 'origin/dev' into better-auth-migration
ntindle Jul 22, 2026
aa6a899
fix(backend): address review — PII, HTML escaping, event-loop, LD cache
ntindle Jul 22, 2026
7a1683b
test(frontend): fix duplicate signup/callback tests broken by the dev…
ntindle Jul 22, 2026
c40dbb4
fix(frontend): close OAuth-callback open redirect + review correctnes…
ntindle Jul 23, 2026
9795f28
refactor(backend): trusted-origin allowlist for auth-email links (dro…
ntindle Jul 23, 2026
0752b9f
fix(frontend): enforce 12-char password floor and converge platform e…
ntindle Jul 23, 2026
86aa33b
fix(platform): address PR review — migration dedup, bridge hardening,…
ntindle Jul 23, 2026
d30a09f
fix(platform): address PR review — OAuth rollback, admin fail-closed,…
ntindle Jul 23, 2026
b5a778f
docs(platform): document JWKS transport-security caveat for self-hosters
ntindle Jul 23, 2026
0b2c071
fix(backend/auth): require JWT_JWKS_URL; JWT_VERIFY_KEY now optional
ntindle Jul 23, 2026
320d404
fix(backend/auth): repair autogpt_libs auth test suite + run it in CI
ntindle Jul 24, 2026
c149745
fix(frontend): mint backend JWT in-process to fix Copilot infinite-lo…
ntindle Jul 24, 2026
a7bf870
fix(backend): route feature-flag AuthUser lookup through DatabaseMana…
ntindle Jul 24, 2026
39e09db
fix(frontend): restore change-email confirmation to the current addre…
ntindle Jul 24, 2026
6461b39
fix(backend/auth): warn on cleartext JWKS transport; clarify config e…
ntindle Jul 24, 2026
3c6540c
refactor(backend): group Better Auth models and mark updatedAt columns
ntindle Jul 24, 2026
8cefacd
refactor(frontend): de-duplicate JWKS alg and callback tests; clarify…
ntindle Jul 24, 2026
3771a29
ci+docs(platform): pin Postgres to 15 to match prod; fix upgrade guide
ntindle Jul 24, 2026
03e1c98
refactor(backend): mount auth-email under /api/auth/email and name it…
ntindle Jul 24, 2026
6e621f1
docs(frontend): name the built-in OAuth exchange in the callback rout…
ntindle Jul 24, 2026
7ae417f
refactor(backend): use the db_accessors user_db() helper for the feat…
ntindle Jul 24, 2026
a0b4fa8
Merge branch 'dev' into better-auth-migration
ntindle Jul 24, 2026
09e291b
fix(backend/auth): declare httpx so the autogpt_libs test suite insta…
ntindle Jul 24, 2026
d1fc1e7
fix(frontend): bound the SSR auth-token self-fetch; untrack Supabase …
ntindle Jul 24, 2026
3d557fc
fix(frontend): stop caching backend JWTs across requests so revocatio…
ntindle Jul 24, 2026
65b1877
fix(frontend): close backslash open-redirect in the auth ?next= guard
ntindle Jul 24, 2026
4ab2d8a
fix(backend/auth): keep the blocking JWKS fetch off the event loop
ntindle Jul 24, 2026
52f09f1
fix(backend): normalize default ports and validate trusted-origin pat…
ntindle Jul 25, 2026
e3dd470
fix(frontend): stop duplicate change-email sends, partial profile upd…
ntindle Jul 25, 2026
5457440
fix(backend/auth): treat a missing role claim as an ordinary user, no…
ntindle Jul 25, 2026
a8e510d
fix(backend): point the websocket auth tests at the async token parser
ntindle Jul 25, 2026
9b2f7f0
fix(frontend): don't consume the legacy cookie when the bridge can't …
ntindle Jul 25, 2026
26955b1
Merge remote-tracking branch 'origin/dev' into better-auth-migration
ntindle Jul 29, 2026
9652ee8
refactor(backend): rename transactional-email senders; fix operationI…
ntindle Jul 29, 2026
7c1cf66
fix(backend/auth): extend migration grace to legacy asymmetric tokens…
ntindle Jul 29, 2026
b2acffe
fix(frontend): migrate Experts marketplace components off the removed…
ntindle Jul 29, 2026
b3ca9c8
refactor(platform): rename Better Auth tables to UserAuth* for clarity
ntindle Jul 29, 2026
6ccbaf5
fix(backend/auth): fail fast on unviable JWKS transport config
ntindle Jul 29, 2026
6fec991
fix(frontend): add tight response-start timeout to the API proxy
ntindle Jul 29, 2026
f62d7e7
refactor(platform): reword review-flagged comments to be timeless and…
ntindle Jul 29, 2026
fe68654
fix(frontend): point direct-upload test mock at the moved getWebSocke…
ntindle Jul 29, 2026
861fc90
fix(frontend): OAuth waitlist rejections now match on the gate's body…
ntindle Jul 29, 2026
ce0136f
fix(frontend): break legacy-cookie redirect loop when the bridge secr…
ntindle Jul 29, 2026
ffc0264
Merge branch 'dev' into better-auth-migration
ntindle Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/claude-dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,7 @@ jobs:
"rabbitmq:management"
"clamav/clamav-debian:latest"
"busybox:latest"
"kong:2.8.1"
"supabase/gotrue:v2.170.0"
"supabase/postgres:15.8.1.049"
"supabase/postgres-meta:v0.86.1"
"supabase/studio:20250224-d10db0f"
"pgvector/pgvector:pg15"
)

# Check if any cached tar files exist (more reliable than cache-hit)
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,7 @@ jobs:
"rabbitmq:management"
"clamav/clamav-debian:latest"
"busybox:latest"
"kong:2.8.1"
"supabase/gotrue:v2.170.0"
"supabase/postgres:15.8.1.049"
"supabase/postgres-meta:v0.86.1"
"supabase/studio:20250224-d10db0f"
"pgvector/pgvector:pg15"
)

# Check if any cached tar files exist (more reliable than cache-hit)
Expand Down
6 changes: 1 addition & 5 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,7 @@ jobs:
"rabbitmq:management"
"clamav/clamav-debian:latest"
"busybox:latest"
"kong:2.8.1"
"supabase/gotrue:v2.170.0"
"supabase/postgres:15.8.1.049"
"supabase/postgres-meta:v0.86.1"
"supabase/studio:20250224-d10db0f"
"pgvector/pgvector:pg15"
)
# Check if any cached tar files exist (more reliable than cache-hit)
Expand Down
97 changes: 73 additions & 24 deletions .github/workflows/platform-backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,50 @@ jobs:
CI: true
PLAIN_OUTPUT: True

# autogpt_libs is a standalone package with its own env; the backend `test`
# job (scoped to autogpt_platform/backend) never collects its tests, so run
# them here. Pure unit tests — no database or external services needed.
autogpt-libs-test:
permissions:
contents: read
timeout-minutes: 10
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: autogpt_platform/autogpt_libs

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Set up Python dependency cache
uses: actions/cache@v5
with:
path: ~/.cache/pypoetry
key: poetry-${{ runner.os }}-py3.12-libs-${{ hashFiles('autogpt_platform/autogpt_libs/poetry.lock') }}

- name: Install Poetry
run: |
HEAD_POETRY_VERSION=$(python ../../.github/workflows/scripts/get_package_version_from_lockfile.py poetry ../backend/poetry.lock)
echo "Using Poetry version ${HEAD_POETRY_VERSION}"
curl -sSL https://install.python-poetry.org | POETRY_VERSION=$HEAD_POETRY_VERSION python3 -

- name: Install Python dependencies
run: poetry install

- name: Run pytest
run: poetry run pytest -q

env:
CI: true
PLAIN_OUTPUT: True

type-check:
permissions:
contents: read
Expand Down Expand Up @@ -210,10 +254,9 @@ jobs:
# picks the right published port per shard.
#
# Not reusing docker-compose.platform.yml directly because compose
# validates the full file even when only some services are ``up``,
# and that file references services (db/kong/...) defined in a
# sibling compose file — pulling both in would needlessly couple
# CI to the full local-dev stack.
# validates the full file even when only some services are ``up``
# — pulling it in would needlessly couple CI to the full
# local-dev stack.
docker network create redis-cluster-ci
for i in 0 1 2; do
port=$((17000 + i))
Expand Down Expand Up @@ -260,11 +303,6 @@ jobs:
docker exec redis-0 redis-cli -p 17000 cluster info >&2 || true
exit 1

- name: Setup Supabase
uses: supabase/setup-cli@v1
with:
version: 1.178.1

- id: get_date
name: Get date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -318,15 +356,28 @@ jobs:
- name: Generate Prisma Client
run: poetry run prisma generate && poetry run gen-prisma-stub

- id: supabase
name: Start Supabase
working-directory: .
- name: Start Postgres
working-directory: autogpt_platform
run: |
supabase init
supabase start --exclude postgres-meta,realtime,storage-api,imgproxy,inbucket,studio,edge-runtime,logflare,vector,supavisor
supabase status -o env | sed 's/="/=/; s/"$//' >> $GITHUB_OUTPUT
# outputs:
# DB_URL, API_URL, GRAPHQL_URL, ANON_KEY, SERVICE_ROLE_KEY, JWT_SECRET
# Plain pgvector Postgres; the init script creates the legacy
# `auth` schema shim that historical migrations reference.
docker run -d --name postgres-test \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=postgres \
-p 5432:5432 \
-v "$(pwd)/db/init/00-init.sql:/docker-entrypoint-initdb.d/00-init.sql:ro" \
pgvector/pgvector:pg15
for _ in $(seq 1 30); do
if docker exec postgres-test pg_isready -U postgres >/dev/null 2>&1; then
echo "Postgres ready"
exit 0
fi
sleep 1
done
echo "Postgres failed to start" >&2
docker logs postgres-test >&2
exit 1

- name: Wait for ClamAV to be ready
run: |
Expand Down Expand Up @@ -360,8 +411,8 @@ jobs:
- name: Run Database Migrations
run: poetry run prisma migrate deploy
env:
DATABASE_URL: ${{ steps.supabase.outputs.DB_URL }}
DIRECT_URL: ${{ steps.supabase.outputs.DB_URL }}
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
DIRECT_URL: postgresql://postgres:postgres@localhost:5432/postgres
Comment thread
cursor[bot] marked this conversation as resolved.

- name: Run pytest with coverage
run: |
Expand All @@ -374,11 +425,9 @@ jobs:
fi
env:
LOG_LEVEL: ${{ runner.debug && 'DEBUG' || 'INFO' }}
DATABASE_URL: ${{ steps.supabase.outputs.DB_URL }}
DIRECT_URL: ${{ steps.supabase.outputs.DB_URL }}
SUPABASE_URL: ${{ steps.supabase.outputs.API_URL }}
SUPABASE_SERVICE_ROLE_KEY: ${{ steps.supabase.outputs.SERVICE_ROLE_KEY }}
JWT_VERIFY_KEY: ${{ steps.supabase.outputs.JWT_SECRET }}
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
DIRECT_URL: postgresql://postgres:postgres@localhost:5432/postgres
JWT_VERIFY_KEY: "ci-only-jwt-verify-key-with-at-least-32-characters" # DO NOT USE IN PRODUCTION!!
Comment thread
cursor[bot] marked this conversation as resolved.
REDIS_HOST: "localhost"
REDIS_PORT: "17000"
ENCRYPTION_KEY: "dvziYgz0KSK8FENhju0ZYi8-fRTfAdlz6YLhdB_jhNw=" # DO NOT USE IN PRODUCTION!!
Expand Down
38 changes: 18 additions & 20 deletions .github/workflows/platform-fullstack-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ jobs:
with:
submodules: recursive

- name: Set up Platform - Copy default supabase .env
- name: Set up Platform - Copy default platform .env
run: |
cp ../.env.default ../.env

Expand Down Expand Up @@ -214,15 +214,13 @@ jobs:
uses: actions/cache@v5
with:
path: /tmp/e2e_test_data.sql
key: e2e-test-data-${{ hashFiles('autogpt_platform/backend/test/e2e_test_data.py', 'autogpt_platform/backend/migrations/**', '.github/workflows/platform-fullstack-ci.yml') }}
key: e2e-test-data-${{ hashFiles('autogpt_platform/backend/test/e2e_test_data.py', 'autogpt_platform/backend/backend/data/user.py', 'autogpt_platform/backend/migrations/**', '.github/workflows/platform-fullstack-ci.yml') }}

- name: Set up Platform - Start Supabase DB + Auth
- name: Set up Platform - Start database
run: |
docker compose -f ../docker-compose.resolved.yml up -d db auth --no-build
docker compose -f ../docker-compose.resolved.yml up -d db --no-build
echo "Waiting for database to be ready..."
timeout 60 sh -c 'until docker compose -f ../docker-compose.resolved.yml exec -T db pg_isready -U postgres 2>/dev/null; do sleep 2; done'
echo "Waiting for auth service to be ready..."
timeout 60 sh -c 'until docker compose -f ../docker-compose.resolved.yml exec -T db psql -U postgres -d postgres -c "SELECT 1 FROM auth.users LIMIT 1" 2>/dev/null; do sleep 2; done' || echo "Auth schema check timeout, continuing..."

- name: Set up Platform - Run migrations
run: |
Expand Down Expand Up @@ -251,7 +249,11 @@ jobs:
run: |
docker compose -f ../docker-compose.resolved.yml up -d --no-build
echo "Waiting for rest_server to be ready..."
timeout 60 sh -c 'until curl -f http://localhost:8006/health 2>/dev/null; do sleep 2; done' || echo "Rest server health check timeout, continuing..."
timeout 180 sh -c 'until curl -f http://localhost:8006/health 2>/dev/null; do sleep 2; done' || {
echo "❌ rest_server did not become healthy in 180s"
docker compose -f ../docker-compose.resolved.yml logs --tail=100 rest_server
exit 1
}
env:
NEXT_PUBLIC_PW_TEST: true

Expand All @@ -266,20 +268,16 @@ jobs:
exit 1
}

# Dump auth.users + platform schema for cache (two separate dumps)
# Dump the platform schema for cache (includes the Better Auth
# user/session/account tables seeded by e2e_test_data.py)
echo "Dumping database for cache..."
{
docker compose -f ../docker-compose.resolved.yml exec -T db \
pg_dump -U postgres --data-only --column-inserts \
--table='auth.users' postgres
docker compose -f ../docker-compose.resolved.yml exec -T db \
pg_dump -U postgres --data-only --column-inserts \
--schema=platform \
--exclude-table='platform._prisma_migrations' \
--exclude-table='platform.apscheduler_jobs' \
--exclude-table='platform.apscheduler_jobs_batched_notifications' \
postgres
} > /tmp/e2e_test_data.sql
docker compose -f ../docker-compose.resolved.yml exec -T db \
pg_dump -U postgres --data-only --column-inserts \
--schema=platform \
--exclude-table='platform._prisma_migrations' \
--exclude-table='platform.apscheduler_jobs' \
--exclude-table='platform.apscheduler_jobs_batched_notifications' \
postgres > /tmp/e2e_test_data.sql

echo "✅ Database dump created for caching ($(wc -l < /tmp/e2e_test_data.sql) lines)"

Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/platform-supabase-auth-sweep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: AutoGPT Platform - Supabase Auth Sweep

# Re-runs the GoTrue -> Better Auth user copy as an idempotent sweep. The
# bulk copy happens in Prisma migration
# 20260716120000_copy_supabase_users_to_better_auth during the normal deploy;
# run this once AFTER the frontend has switched to Better Auth to catch users
# who signed up via GoTrue in between.

on:
workflow_dispatch:
inputs:
environment:
description: "Environment to sweep"
type: choice
required: true
options:
- develop
- production

permissions:
contents: "read"

jobs:
sweep:
environment: ${{ github.event.inputs.environment }}
name: Sweep GoTrue users into Better Auth
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: autogpt_platform/frontend/package.json

- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: "24.18.0"
cache: "pnpm"
cache-dependency-path: autogpt_platform/frontend/pnpm-lock.yaml

- name: Install dependencies
working-directory: ./autogpt_platform/frontend
run: pnpm install --frozen-lockfile

- name: Run sweep
working-directory: ./autogpt_platform/frontend
run: npx tsx scripts/migrate-supabase-auth.ts
env:
DATABASE_URL: ${{ secrets.BACKEND_DATABASE_URL }}
Comment thread
ntindle marked this conversation as resolved.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,6 @@ test-screenshots/
.ign*
**/.ign*
.claude/scheduled_tasks.lock

# Supabase CLI machine-local state (linked project ref, etc.)
supabase/.temp/
2 changes: 2 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ We take the security of our project seriously. If you believe you have found a s

> **Important Note**: Any code within the `classic/` folder is considered legacy, unsupported, and out of scope for security reports. We will not address security vulnerabilities in this deprecated code.

> **Important Note**: The JWKS transport check (the startup warning when `JWT_JWKS_URL` is fetched over cleartext `http://` from a non-local host) is best-effort operator guidance, not a security boundary. It is a warning only, it never blocks startup, and it cannot tell a trusted private network from a hostile one. Securing the network path between the backend and the JWKS endpoint is the operator's responsibility — see the self-hosting security note in `docs/platform/getting-started.md`. Reports that the warning can be missed, silenced, or evaded are not eligible for a CVE.

Instead, please report them via:
- [GitHub Security Advisory](https://github.com/Significant-Gravitas/AutoGPT/security/advisories/new)
<!--- [Huntr.dev](https://huntr.com/repos/significant-gravitas/autogpt) - where you may be eligible for a bounty-->
Expand Down
Loading
Loading