Skip to content

Fix administrator setup validation and recovery UX#169

Open
support371 wants to merge 6 commits into
mainfrom
fix/admin-access-validation
Open

Fix administrator setup validation and recovery UX#169
support371 wants to merge 6 commits into
mainfrom
fix/admin-access-validation

Conversation

@support371

@support371 support371 commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Problem

The live administrator password form accepted submissions but /api/admin-access returned 400 because the matching one-time authorization row was absent or expired. The page also attempted /api/admin-access/validate, which was not deployed on main, causing a 404 and leaving the user without an actionable diagnosis.

Fix

  • Add /api/admin-access/validate.
  • Validate the browser capability against the atomic Supabase validation RPC before showing the password form.
  • Show clear states for missing, invalid, expired, or unregistered authorization.
  • Prevent password submission until database authorization is confirmed.
  • Provide a direct restart path to the owner-controlled authorization flow.
  • Keep capabilities out of URLs after capture and preserve no-store/no-referrer behavior.

Safety

  • No password or usable capability is stored in GitHub.
  • No database credentials are added.
  • No admin account is automatically modified.
  • Existing one-time atomic consumption remains unchanged.

Summary by Sourcery

Add server-side token validation and improved UX for administrator password setup to ensure only active, registered browser capabilities can reach the password screen.

New Features:

  • Introduce an admin access validation API endpoint that checks browser capabilities against a Supabase RPC before allowing password setup.
  • Add a Supabase-backed token validation helper that hashes the browser capability and queries a secure database function.
  • Provide clear UI states and flows for missing, invalid, or expired administrator setup authorizations, including a guided restart path from the authorize page.

Enhancements:

  • Tighten administrator setup copy and messaging to emphasize full SQL execution, database confirmation, and capability lifecycle.
  • Ensure setup capabilities are removed from URLs after capture while keeping password entry gated behind confirmed database authorization.

Deployment:

  • Add a database migration that creates a secure gem_validate_admin_access_token function for validating admin access tokens using hashed values.

Tests:

  • Add unit tests for administrator access token validation to cover hash-only transmission, invalid authorization results, and unavailable validation service behavior.

@gitguardian

gitguardian Bot commented Jul 13, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
34768571 Triggered JSON Web Token d9e8ceb src/lib/admin-access-validation.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai

sourcery-ai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements server-side and client-side validation of the one-time administrator setup capability before allowing password creation, adds UX for missing/invalid/expired authorization, and wires this through a new Supabase-backed validation RPC and API route with tests and a migration.

Sequence diagram for admin access token validation before password setup

sequenceDiagram
  actor Owner
  participant AdminAccessAuthorizePage as AdminAccessAuthorizePage
  participant AdminAccessPage as AdminAccessPage
  participant ApiValidate as Api_admin-access-validate_POST
  participant SupabaseRPC as Supabase_gem_validate_admin_access_token

  Owner->>AdminAccessAuthorizePage: generateAdminAccessAuthorization()
  AdminAccessAuthorizePage->>Owner: Show SQL and token
  Owner->>SupabaseRPC: Run SQL in Supabase

  Owner->>AdminAccessAuthorizePage: click verifyAndContinue()
  AdminAccessAuthorizePage->>ApiValidate: POST /api/admin-access/validate {accessToken}
  ApiValidate->>SupabaseRPC: POST /rest/v1/rpc/gem_validate_admin_access_token {p_token_hash}
  SupabaseRPC-->>ApiValidate: {valid, expires_at, request_id}
  ApiValidate-->>AdminAccessAuthorizePage: {valid, expiresAt, requestId}
  AdminAccessAuthorizePage->>AdminAccessPage: window.location.assign(/admin-access#token=...)

  AdminAccessPage->>ApiValidate: POST /api/admin-access/validate {accessToken}
  ApiValidate->>SupabaseRPC: POST gem_validate_admin_access_token {p_token_hash}
  SupabaseRPC-->>ApiValidate: {valid}
  ApiValidate-->>AdminAccessPage: {valid}
  AdminAccessPage->>AdminAccessPage: tokenState = valid
  AdminAccessPage->>AdminAccessPage: submit() allowed only when tokenState === valid
Loading

File-Level Changes

Change Details Files
Add browser-side validation and gating of the admin setup capability before showing the password form and submitting the password.
  • Replace simple URL-fragment capture with a token state machine that calls the new validation API and tracks checking/valid/invalid/missing states.
  • Block password submission unless the token state is valid and all password requirements are met.
  • Adjust loading, success, and error views to reflect database authorization status, including restart links and clearer copy.
src/app/admin-access/page.tsx
Add a verification step to the authorization flow so the browser capability is checked against the database before redirecting to the password setup page.
  • Replace the manual SQL-confirmation checkbox with an async verify-and-continue action that calls the validation API and only redirects on success.
  • Track verifying/verified state to drive button label, disabled state, and loading indicators.
  • Tighten and clarify instructional copy around generating the capability, copying the SQL, running it in Supabase, and restarting the flow; ensure error messages explain how to recover.
src/app/admin-access/authorize/page.tsx
Introduce a shared library for validating admin access tokens against Supabase via a dedicated RPC, ensuring only the SHA-256 hash is sent and failures are safe-by-default.
  • Implement helper functions to derive the Supabase project URL and publishable key from environment variables with secure defaults.
  • Add a SHA-256 hex hashing utility and use it to hash the browser capability before calling the RPC.
  • Implement validateAdminAccessToken() to call the Supabase RPC, enforce no-store caching, parse the response into a typed result, and throw on non-OK responses.
src/lib/admin-access-validation.ts
Expose a new rate-limited API endpoint for admin access validation that wraps the Supabase RPC and returns UX-friendly status and messages.
  • Define a strict Zod schema for the request body and return 400s for invalid JSON or malformed capabilities.
  • Integrate existing IP-based rate limiting with a dedicated key and 15-minute window to protect the validation endpoint.
  • Call the shared validation helper, map its result into a JSON response with valid/expiresAt/requestId/message fields, and handle downstream failures with a 503 and generic error.
  • Set response headers to enforce no-store caching and no-referrer policy to keep capabilities out of logs and referrers.
src/app/api/admin-access/validate/route.ts
Add automated tests to ensure the validation helper only sends hashed tokens, correctly interprets RPC responses, and fails closed when the validation service is unavailable.
  • Mock global fetch to assert that only p_token_hash is sent, that it is a 64-character hex string, and the raw access token never appears in the request body.
  • Verify that an RPC response indicating no active authorization row yields a valid:false result with null metadata.
  • Verify that non-OK RPC responses cause validateAdminAccessToken to throw a specific error message indicating validation is unavailable.
src/__tests__/admin-access-validation.test.ts
Add a Supabase database function to validate admin access token hashes against the admin_access_tokens table with strict constraints on the administrator account.
  • Create gem_validate_admin_access_token(p_token_hash text) returning valid, expires_at, and request_id, with early return on invalid hash length.
  • Query admin_access_tokens joined to users with constraints on token usage, expiry, admin email, allowed roles, and verified/active status; return false with nulls when no row matches.
  • Return true with the token’s expiry and request_id when a matching row exists.
  • Restrict function execution by revoking public/authenticated access and granting EXECUTE only to anon, aligning with use via the anon key.
prisma/migrations/20260713020500_add_admin_access_token_validation/migration.sql

Possibly linked issues

  • #Restore end-to-end admin access through Supabase gateway: PR adds Supabase RPC, API route, and UI flows for validating one-time admin setup capabilities, matching gateway setup goals.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 security issue, and left some high level feedback:

Security issues:

  • Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data. (link)

General comments:

  • The hardcoded DEFAULT_SUPABASE_URL and DEFAULT_SUPABASE_ANON_KEY in admin-access-validation.ts effectively bake environment-specific credentials into the codebase; consider moving these to environment variables with safer defaults and using explicit test-only values in the unit tests instead.
  • The PL/pgSQL function gem_validate_admin_access_token hardcodes the administrator email and role/status constraints; if you ever need to support different admin identities or environments, consider parameterizing or centralizing these checks rather than duplicating them in the function.
  • In the new /api/admin-access/validate route, the generic 400 error message "Invalid authorization capability." may make debugging harder when schema validation fails; consider returning more specific feedback based on Zod’s parse errors while still avoiding leakage of sensitive details.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The hardcoded DEFAULT_SUPABASE_URL and DEFAULT_SUPABASE_ANON_KEY in `admin-access-validation.ts` effectively bake environment-specific credentials into the codebase; consider moving these to environment variables with safer defaults and using explicit test-only values in the unit tests instead.
- The PL/pgSQL function `gem_validate_admin_access_token` hardcodes the administrator email and role/status constraints; if you ever need to support different admin identities or environments, consider parameterizing or centralizing these checks rather than duplicating them in the function.
- In the new `/api/admin-access/validate` route, the generic 400 error message "Invalid authorization capability." may make debugging harder when schema validation fails; consider returning more specific feedback based on Zod’s parse errors while still avoiding leakage of sensitive details.

## Individual Comments

### Comment 1
<location path="src/lib/admin-access-validation.ts" line_range="3" />
<code_context>
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InNsemRqb3FwemJrd3p1YWV4bGtqIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODMyOTk1MTQsImV4cCI6MjA5ODg3NTUxNH0.0wfgX_m6SBn_TtD0ZNjkOZ-bk8Frp2Tq1HL9mYFBm4M
</code_context>
<issue_to_address>
**security (jwt):** Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

*Source: betterleaks*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -0,0 +1,70 @@
const DEFAULT_SUPABASE_URL = "https://slzdjoqpzbkwzuaexlkj.supabase.co";
const DEFAULT_SUPABASE_ANON_KEY =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InNsemRqb3FwemJrd3p1YWV4bGtqIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODMyOTk1MTQsImV4cCI6MjA5ODg3NTUxNH0.0wfgX_m6SBn_TtD0ZNjkOZ-bk8Frp2Tq1HL9mYFBm4M";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security (jwt): Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

Source: betterleaks

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 13, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
gem-enterprise 40229ae Jul 13 2026, 03:44 AM

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.

1 participant