Run mix ithibati.doctor in the consuming application after configuring Ithibati and running migrations. It starts your application and checks the integration against its database.

$ mix ithibati.doctor

A healthy run ends with Nothing to fix. and exits zero. Failures are labelled bad; optional checks that do not apply are labelled skip. Fix the reported setup and rerun the command.

What it checks

The doctor combines configuration validation with checks that require a running application:

AreaWhat to check when it fails
Account configurationuser_schema names the expected schema and repo names the Ecto repo
Database adapterThe repo uses Ecto.Adapters.Postgres, Ecto.Adapters.SQLite3 or Ecto.Adapters.MyXQL
Database connectionThe repo is started and reachable; SQLite foreign keys are enabled; MySQL uses READ COMMITTED and enabled foreign-key checks; neither uses schema prefixes
Ithibati tablesMigrations ran with the same table-name prefix used by the compiled schemas
Account primary keyThe database column matches users_key_type and has the required uniqueness
Account identifierThe column exists and has the required unique index
Invitation tableWhen configured, the table exists and token_hash has its unique index
Handler callbacksEach discovered handler implements the four required callbacks
Mounted handlersRouter mounts refer to available handler modules
Session validityThe value uses a positive count and a supported unit
Initial claimThe configured mode is :open or :operator_code; the version 3 code table exists
WebAuthn configurationNo unused wax_ origin or RP-ID settings are misleading the integration

The complete set is defined in Ithibati.Doctor; this table groups related checks by the action you can take. Configuration and schemas explains the settings and indexes.

Common fixes

Unsupported database adapter

Ithibati supports PostgreSQL, SQLite and MySQL for catalogue checks and credential locking. The doctor checks the repo's adapter before issuing SQL. With another adapter, it reports the repo and adapter names and skips connection, table and index checks. Independent configuration and web-integration checks still run.

Configure Ithibati with a repo using Ecto.Adapters.Postgres, Ecto.Adapters.SQLite3 or Ecto.Adapters.MyXQL. This check does not require a connection, but the Mix task still starts your application before running the doctor.

Missing tables or an unexpected prefix

Run your migrations against the same database the application uses. table_prefix: "auth" means names such as auth_sessions; it does not select a PostgreSQL schema.

SQLite supports only the unprefixed main database. On PostgreSQL, the doctor uses the repo's default migration schema prefix. If you migrated with an explicit mix ecto.migrate --prefix tenant1, compare that with the schema named in the report.

Missing identifier index

A changeset validation alone cannot prevent concurrent registrations from storing the same identifier. Restore the unique index required by the account schema. If you chose unique_index: false, your own migration must maintain it.

Invitations enabled after initial setup

Ithibati's original migration is already recorded as applied. Creating the invitation table later must also create its token index. Use Ithibati.Migration.invitation_index(version: 4) in that migration, as shown in the invitation guide.

Invitation table without the inviter column

ithibati_invitation/0 declares invited_by_id from version 4, so every invitation query asks for it. A table created before then still has to gain it, and the migration that built it has already run. Add the column in a new migration with Ithibati.Migration.invitation_inviter_column(version: 4), as the invitation guide shows. The same check refuses a column whose type does not match config :ithibati, users_key_type:.

Missing handler callback

Implement registration_subject/2, register/4, authenticate/2 and recovered/3. The recovery callback must handle both nil and a fresh code batch. See Recovery codes.

Unused wax_ settings

Ithibati passes the relying-party ID and origin explicitly. Configure the endpoint's public URL or implement the handler's optional relying_party/2 callback, as described in The relying party.

Add it to a check command

In your application's mix.exs, include the doctor in a check alias after compilation:

defp aliases do
  [precommit: ["compile --warnings-as-errors", "ithibati.doctor", "test"]]
end

Merge this into your existing aliases. The environment running it needs working application configuration, a started repo and a reachable, migrated database.

For a programmatic result, call Ithibati.Doctor.examine/1 with the application's name. It returns the findings as data without requiring Mix. Call it once the relevant application processes and repo are available.

What to verify separately

The doctor checks installation state. It does not exercise templates, asset imports, browser passkey prompts or your application's authorization policy. Complete the browser flow at the end of Getting started as well.

Credo checks complement it by inspecting integration code.