fix(auth): serve /docs and llms.txt to anonymous agents (#1520)

The middleware allowlist never included the agent-discovery surfaces, so
every anonymous request to /llms.txt, /llms-full.txt, or /docs/* was
307-bounced to /login on hosted. The llms.txt convention exists for
logged-out crawlers and IDE agents, and /docs is the public API
documentation that the OpenAPI spec and the installable accounted-api
skill link to. openapi.json and /.well-known/* only escaped because the
proxy matcher skips .json and .well-known paths.

Signed-in users fall through to the same content with no redirect.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-11 14:01:00 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent bf220eac3c
commit 709c0c817a
2 changed files with 43 additions and 0 deletions
+17
View File
@@ -201,6 +201,23 @@ export async function updateSession(request: NextRequest) {
return supabaseResponse
}
// Public agent-discovery + API docs surfaces. /llms.txt and /llms-full.txt
// exist FOR anonymous consumers (the llms.txt convention targets logged-out
// crawlers and IDE agents), and /docs is the public API documentation the
// OpenAPI spec and the installable accounted-api skill link to. None of it
// reads the session. Without this branch every anonymous hit 307-bounced to
// /login, which silently broke agent discovery on the hosted product
// (openapi.json only escaped because the proxy matcher skips .json paths).
// Logged-in users fall through to the same content: no redirect either way.
if (
pathname === '/llms.txt' ||
pathname === '/llms-full.txt' ||
pathname === '/docs' ||
pathname.startsWith('/docs/')
) {
return supabaseResponse
}
// Public auth routes: allow access
if (
pathname.startsWith('/login') ||