Skip to content

fix: bootstrap Passport personal access client#206

Open
drbelt27 wants to merge 1 commit into
trypostit:mainfrom
drbelt27:fix/passport-personal-access-bootstrap
Open

fix: bootstrap Passport personal access client#206
drbelt27 wants to merge 1 commit into
trypostit:mainfrom
drbelt27:fix/passport-personal-access-bootstrap

Conversation

@drbelt27

Copy link
Copy Markdown

Summary

This change bootstraps the Laravel Passport Personal Access Client required for API key creation in production Docker deployments.

It adds a focused Artisan command, trypost:bootstrap-passport, and invokes it from the production entrypoint after database migrations and Passport key initialization.

Problem

A fresh production deployment can have:

  • all Passport migrations applied;
  • Passport public and private keys present;
  • all OAuth tables available;

while still having no Personal Access Client in oauth_clients.

When a user creates an API key from the workspace settings, TryPost calls User::createToken(...). Laravel Passport then fails with HTTP 500:

Personal access client not found for 'users' user provider. Please create one.

Reproduction

  1. Start with a fresh production database.
  2. Run the database migrations.
  3. ensure Passport keys are available.
  4. Do not execute PassportSeeder.
  5. Open the workspace API key settings.
  6. Attempt to create an API key.
  7. Observe the HTTP 500 exception indicating that the Personal Access Client is missing.

Root cause

TryPost already contains Database\Seeders\PassportSeeder, and the main DatabaseSeeder includes it.

However, the production Docker entrypoint runs migrations and prepares Passport keys without running the focused Passport seeder.

As a result, the application can start successfully while User::createToken(...) remains unusable because no active Personal Access Client exists.

Solution

This pull request:

  • adds the trypost:bootstrap-passport Artisan command;
  • invokes only Database\Seeders\PassportSeeder;
  • runs the command during production container startup after migrations and Passport key preparation;
  • does not run the full DatabaseSeeder;
  • does not regenerate Passport keys;
  • does not hide bootstrap failures behind || true;
  • exits with a non-zero status and a clear message if the bootstrap fails.

Idempotency and concurrency

The bootstrap is designed to be safe across repeated and concurrent production starts.

It:

  • reuses an existing active Personal Access Client;

  • supports valid clients with either a null provider or the users provider;

  • does not create duplicates during repeated starts;

  • does not revoke or replace valid clients;

  • does not invalidate existing access tokens;

  • creates a new valid client when only revoked clients exist;

  • serializes concurrent bootstrap attempts using:

    • PostgreSQL advisory locks;
    • MySQL/MariaDB GET_LOCK.

Locks are released after execution, including failure paths.

Testing

Full test suite

2744 passed
21374 assertions
3 skipped
Duration: 1886.01s

The full suite was executed against a dedicated local PostgreSQL test database. No production database or production credentials were used.

Focused bootstrap tests

php artisan test tests/Feature/PassportBootstrapCommandTest.php --compact

10 passed
34 assertions
Duration: 47.83s

Related API key tests

PassportBootstrapCommandTest + ApiKeyControllerTest

19 passed
59 assertions
Duration: 57.46s
PassportBootstrapCommandTest + Api/ApiKeyApiTest

16 passed
54 assertions
1 skipped
Duration: 43.02s
PassportBootstrapCommandTest + Mcp/ApiKeyToolTest

19 passed
76 assertions
Duration: 53.65s

Additional checks

  • focused Pint check: passed;
  • git diff --check: passed;
  • bash -n docker/entrypoint.sh: passed;
  • ShellCheck was not available in the local environment.

The local test environment used a dedicated PostgreSQL database named trypost_test and isolated Passport test keys. No production environment was involved.

Backward compatibility

Existing installations with a valid Personal Access Client remain unchanged.

This change does not:

  • regenerate Passport keys;
  • revoke Personal Access Clients;
  • replace valid clients;
  • invalidate existing access tokens;
  • run the full application seeder;
  • change the public API behavior beyond ensuring the required Passport client exists.

Scope

This pull request only addresses Passport Personal Access Client bootstrap during production Docker startup.

It does not include:

  • MCP Asset Library changes;
  • Reverb or frontend configuration changes;
  • deployment infrastructure specific to any installation;
  • unrelated refactors;
  • backup, monitoring, SMTP, or reverse proxy configuration.

Risk

The risk is low and limited to production startup.

The entrypoint now fails explicitly when Passport bootstrap cannot complete. This is preferable to allowing the application to start successfully while API key creation remains broken with an HTTP 500 error.

Rollback

Rollback consists of reverting this commit.

Any Personal Access Client already created remains valid, and existing clients and tokens are not modified by the rollback.

Reviewer notes

The main review points are:

  • the focused trypost:bootstrap-passport Artisan command;
  • its position in the production entrypoint after migrations and Passport key preparation;
  • the idempotency behavior;
  • database locking for concurrent starts;
  • preservation of existing clients and tokens;
  • regression coverage for API key creation.

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