Automatic auth catalog
Kurabase has a small, chain-backed, pseudonymous auth catalog. It is a convenience for application queries after a user has already authenticated; it is not an authentication provider, an authority registry, or evidence that a caller is authenticated.
System relations
The current implementation exposes two reserved relations in the public SQL catalog:
| Relation | Columns | Purpose |
|---|---|---|
kura_auth_users | id text primary key | One canonical application user ID. |
kura_auth_identities | id text primary key, user_id text (FK to kura_auth_users.id), provider text, wallet_address text | A deterministic identity record linked to that user. provider is wallet or privy. |
kura_auth_identities.id is a deterministic hash of the provider, canonical
user ID, and wallet address. It is an identifier for this catalog record, not
an authentication credential. The catalog does not mint, validate, extend, or
revoke sessions.
There is currently no auth schema or auth.* namespace. Use the exact
relation names above. In particular, auth.uid() and auth.jwt() are SQL
context helpers, not tables, views, or a Supabase Auth compatibility promise.
Bootstrap and compatibility
At startup, only a gateway whose current on-chain grant is privileged creates the two relations. It creates both definitions atomically. An ordinary gateway only replays catalog metadata; it does not initialize it.
Startup is idempotent: when both relations already exist, Kurabase validates their reserved definitions and leaves the rows unchanged. If only one exists, or either definition was changed, startup fails rather than overwriting an occupied name. Operators retain administrative SQL control through the privileged gateway, but should treat these relation names and definitions as reserved system state.
Registration during session exchange
Registration happens only after the gateway has verified an existing,
independently signed user-session envelope. It uses that same user session for
the resulting chain commit; it does not switch to a privileged execution path.
Repeating the same successful exchange is idempotent (ON CONFLICT DO NOTHING).
Only these canonical forms are recorded:
| Provider | kura_auth_users.id | Catalog record |
|---|---|---|
| Wallet | The lower-case canonical EVM address, equal to the signing wallet | provider = 'wallet', same lower-case address in wallet_address |
| Privy-attested identity | did:privy: followed by 1–128 ASCII letters, digits, _, or - | provider = 'privy', with the verified session wallet in wallet_address |
Other valid session subjects remain usable for RLS but are intentionally not
cataloged. Arbitrary claims, email-like subjects, raw claims, access tokens,
and identity tokens are never registered. A did:privy: test subject is only a
strict pseudonymous format check; it is not live Privy verification.
For a live Privy flow, verify both token channels and issue the signed envelope
through an external identity signer. The SDK then sends the envelope—not Privy
tokens—to /auth/v1/session. See JavaScript SDK.
Application visibility and writes
Both system relations enable RLS and have only an authenticated SELECT
policy:
-- equivalent policies
USING (id = auth.uid()) -- kura_auth_users
USING (user_id = auth.uid()) -- kura_auth_identities
Consequently an authenticated user can read only their own catalog records;
anonymous callers see none. REST client writes are not an application API for
this catalog: there are no user INSERT, UPDATE, or DELETE policies.
Attempts to insert are rejected, and update/delete requests cannot gain a
permissive target through these SELECT-only policies. The session-exchange path
is the sole automatic registration path.
This is access visibility, not confidentiality. All committed EVM cells, including the canonical IDs, deterministic hashes, provider labels, and wallet addresses in this catalog, are public-chain data. Do not use the catalog for email addresses, profiles, secrets, tokens, or any other confidential or personal data.
Current boundary
The catalog is deliberately a narrow first slice. It does not provide a
general auth.* API, user-management REST endpoints, a hosted identity
provider, or native Privy token verification inside the gateway. Those remain
separate provider and application responsibilities.