Skip to main content
Identity plugin · listing tai42/accounts-postgres

Install

Permissions

Provides

accounts-postgres

Identity — Postgres-backed accounts/identity provider — owns user accounts, password login, sessions, and invites.

login

Router — The public /api/login/* routes.

users

Router — The authed /api/auth/users/me/password self-service password route. Provides human logins on Postgres — an email and password, a session, and a role. Member administration is the Studio’s own generic Members page over the provider’s declared member actions, so this plugin ships no Studio page of its own. The account model itself stays central; see Accounts. This page wires the provider and its two routers.

accounts-postgres

The identity provider. Mount it with both routers and register it as an auth provider:
manifest.yml
Mounting the routes without registering the provider raises at boot, naming both settings — the two halves are never half-wired.

Connect the database

The provider carries no connection of its own. It binds to a named database through TAI_DB_BINDING_TAI42_ACCOUNTS_POSTGRES (default default) and uses that database’s connection, keeping its own tables inside it. A single-database deployment leaves the binding unset and configures TAI_DATABASE_DEFAULT_PG_*; give accounts its own database by binding it to another declared name and configuring that one:
The provider is on when its bound database is configured — a non-empty password — and cleanly off otherwise. Pool sizes and timeouts are tuned on the database itself (TAI_DATABASE_<NAME>_PG_*), not a variable of this package’s own. Sessions live in Postgres. The login throttle’s counters (per-account backoff and per-IP failures) live in Redis, on the plugin’s own connection: TAI_ACCOUNTS_REDIS_URL, falling back to TAI_DEFAULT_REDIS_URL. A login with no reachable Redis fails closed.

Run the migrations

The plugin ships a migrations/ folder and declares it in its descriptor, so the shared runner discovers it as the tai42-accounts-postgres component and applies it alongside the core chain:
The platform checks this chain at every boot and reload and never applies it for you: with the store configured but the chain pending, the process refuses to start, naming tai db migrate.

Tune sessions and login limits

login

The public /api/login/* routes: POST /api/login/password verifies an email and password and mints a session, and POST /api/login/invite/accept sets a first password from an invite. Passwords are at least ten characters. The first owner is not created here. The platform’s one-step setup door creates the owner principal and, when this provider is configured, attaches the owner’s login through it — a password set now, or an invite link the owner follows later to set one. The provider implements that attachment seam and owns no separate first-owner route.

users

PUT /api/auth/users/me/password is the one route this module carries: a signed-in person changing their OWN password, which revokes every other session. It is self-service, not member administration, so it is open to every user, not just an admin. Member administration is not routes here. The provider declares its member actions — invite a user, send a new login link, cancel an invitation, change a member’s role or access, and remove a member — through the platform’s generic member-actions seam, and the Studio’s own generic Members page renders them. The provider declares its display name, “Postgres”, which the Members page shows on each of its member and invitation rows and beside each of its page actions. There is no outbound email: inviting a user (or sending a new link) returns a one-time invite token and a /login?invite=... path relative to your origin (the deployment’s declared login page and invite key, HOSTED_UI_LOGIN_PATH and HOSTED_UI_INVITE_QUERY_KEY), shown once on the action’s result; the invitee sets a password through POST /api/login/invite/accept, which consumes the token and mints a session in one step. role names an existing access-control role template; an unknown name is rejected and no user is created. A member’s role is read from the platform — the role their principal holds, or No role when their access was not set from a role. The platform refuses a change that would leave no enabled admin principal, and every admin principal counts, not only accounts; see the last enabled admin stays.

Login throttles behind a proxy

The per-IP login counters key on the client the platform resolves for every public door: the direct peer unless you declare your proxies with TAI_RATE_LIMIT_TRUSTED_PROXIES or TAI_RATE_LIMIT_TRUSTED_HOPS, in which case the forwarded client. An IPv6 client is counted by its /64. See which client a request is from.

See also