Skip to content

fix(auth): urlcode-auth migrate --host-file creates a plugin's schema - #1149

Merged
jimhoyd merged 1 commit into
mainfrom
claude/auth-migrate-host-plugins-8d83ux
Oct 7, 2026
Merged

jimhoyd merged 1 commit into
mainfrom
claude/auth-migrate-host-plugins-8d83ux

Conversation

@jimhoyd

@jimhoyd jimhoyd commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Requested by Jimmy · project thread

Fixes #1140.

Problem and change

Before: a site that passed a schema-adding Better Auth plugin (for example admin) through auth({betterAuth: {plugins}}) on the bundled SQLite file could not serve. Activation refused and said to run npx urlcode-auth migrate, but that command never read host.mjs, so it never created the plugin's tables. urlcode test and audit still passed.

After: npx urlcode-auth migrate --host-file host.mjs creates the plugin's tables and columns, and the site serves. create-user and find-user take the same flag. When plugins are configured, the activation refusal names --host-file host.mjs. A hermetic run (test, audit, a --local-review validate) logs one extension_warning that names the tables the plugins add and the command that creates them, so a passing audit no longer hides the gap.

How: the CLI loads the host file with core's read-only inspection load. That is the load urlcode explain --host-file uses: it needs no revision pin and serves nothing. Core's @jimhoyd/urlcode/host now exports this as inspectOperatorHost. The auth extension's served host() puts the database, secret and betterAuth options it was given on its registration, as a non-enumerable Symbol.for('urlcode.auth.operatorSettings') property, and the CLI builds Better Auth's options from that. So a database path or secretFile set in host.mjs is also used now. --project (default <site>/app) names the route project the host file must stay outside, which is the check core already makes. Without --host-file, the commands behave as before. The only change there is wording: the owner-database refusal now says "the bundled SQLite file" instead of data/auth.sqlite.

Verification

  • test/account-composition.test.ts: the fourth test (the [Bug]: a schema-adding Better Auth plugin on the bundled SQLite file is refused with a remedy (urlcode-auth migrate) that cannot work, while test and audit pass #1140 repro) now goes end to end through the real CLIs with a host.mjs that composes auth({betterAuth: {plugins: [admin()]}}). It checks that a local-review validate passes and logs the warning, that plain migrate followed by a pinned validate refuses with the --host-file remedy, that migrate --host-file followed by a pinned validate passes, and that create-user and find-user --host-file work and the user row has role and banned. It also checks that a host file without auth is refused by name.
  • packages/auth npm test: 33/33 pass (the owner-database refusal regex was updated for the new wording).
  • auth-validate-stderr, core-boundaries, extension-warnings, extensions and extension-reference tests: 124/124 pass.
  • npm run typecheck (root and auth), npm run lint, npm run check:docs, npm run build, npm run test:package:built: all clean.

Compatibility and security

  • No YAML or schema change. The new CLI flags are opt-in, and there is one new core export (inspectOperatorHost).

  • The host file is trusted operator code, already imported by explain, serve and others. The settings property holds the secret in process only. It is non-enumerable and symbol-keyed, so it does not serialize.

  • The hermetic warning appears on every test or audit run of a site with schema-adding plugins, because a hermetic run cannot inspect the live database.

  • Changes match the documented portable contract; docs/examples are updated where needed.

  • Relevant tests and package checks pass, or limitations are explained above.

  • No credentials, customer data or private project material are included.

  • Runtime/starter changes remain aligned where applicable.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y6eJKxRdhiRJCwZ4rJ6q7b


Generated by Claude Code

…#1140)

With a schema-adding Better Auth plugin (admin) passed through
auth({betterAuth: {plugins}}) on the bundled SQLite file, activation
refused and named `urlcode-auth migrate`, which never read host.mjs and
so never created the plugin's tables, while test and audit passed.

- urlcode-auth migrate, create-user and find-user take --host-file (and
  --project, default <site>/app). They load the host file through core's
  inspection load (new inspectOperatorHost in @jimhoyd/urlcode/host) and
  use the database, secret and Better Auth options host.mjs passes auth(),
  carried on the served registration under a Symbol.for key.
- The activation refusal names --host-file host.mjs when plugins are set.
- A hermetic run (test, audit, local-review validate) logs one
  extension_warning naming the tables the plugins add and that command.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6eJKxRdhiRJCwZ4rJ6q7b
@jimhoyd jimhoyd self-assigned this Oct 7, 2026
@jimhoyd
jimhoyd marked this pull request as ready for review October 7, 2026 19:42
@jimhoyd
jimhoyd merged commit 91fb65d into main Oct 7, 2026
24 checks passed
@jimhoyd
jimhoyd deleted the claude/auth-migrate-host-plugins-8d83ux branch October 7, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants