import { TableLike } from '@voltro/database'; /** Tables the plugin contributes, as an array. */ export declare const authTables: readonly [TableLike, TableLike, TableLike, TableLike, TableLike, TableLike, TableLike, TableLike, TableLike, TableLike]; /** * Auth-token table. Single-use, hashed, expiring tokens for the * magic-link sign-in + password-reset flows. We store only the SHA-256 * of the token (never the plaintext) so a DB leak can't be replayed. * `purpose` discriminates the flow; `consumedAt` is set the first time * a token is redeemed (single-use guard). */ export declare const authTokensTable: TableLike; /** * Impersonation grants — one row per "support agent A is acting as user B", * written when the impersonated session is minted and closed when it ends. * * This table is the reason impersonation is auditable AT ALL without the app * wiring anything: the session it describes is, by design, indistinguishable * from B's own session everywhere downstream (same subject id, same tenant, * same authority), so the fact that A is behind it exists in exactly two * places — the session's `metadata.impersonation` mark, and this row. The mark * can be dropped by an audit redaction policy; the row cannot. * * `sessionId` is UNIQUE and points at the `sessions` row for the impersonated * session, which is what makes ending a grant a real revocation rather than a * bookkeeping update: the stop path deletes that session row, and the * request-time revocation check kills the cookie with it. * * `actorSessionId` is the IMPERSONATOR's own session, kept alive throughout so * stopping restores them to their own identity instead of signing them out. */ export declare const impersonationGrantsTable: TableLike; /** * Tenant invitations — one row per "you have been invited to as * ". The row IS the grant: accepting it writes the membership. * * Shaped like `authTokens` on purpose (hashed single-use token, `expiresAt`, * a consumed stamp) because it has the same threat model — the plaintext only * ever travels in the email, so a database leak yields no usable invitation. * What it adds over a token row is the thing an invitation IS and a token is * not: WHO it was addressed to, WHICH tenant it opens, and — the security * property that decides the whole feature — WHAT ROLE it grants. * * `role` is written by the INVITER at creation and read at acceptance. The * accept endpoint takes a token and nothing else, so an invitee cannot name * their own role; the only way to change a pending invitation's role is to * revoke it and issue another. * * Terminal states are all stamps rather than a `status` string, so a row can * never claim two of them: `acceptedAt` (redeemed), `revokedAt` (withdrawn), * and past `expiresAt` (lapsed). `acceptInvitation` matches on all three * being clear in ONE conditional UPDATE, which is what makes acceptance * single-use under concurrency rather than by convention. */ export declare const invitationsTable: TableLike; /** * Login-attempt counters for brute-force lockout, keyed by normalized * email — NOT by user id. Tracking the EMAIL (whether or not a user row * exists) is what keeps a locked account from leaking its existence: an * unknown email that has been hammered locks exactly like a real one, so * the refusal is uniform. `handleSignIn` records a failure on every wrong * credential and clears the row on a completed login. */ export declare const loginAttemptsTable: TableLike; /** * Memberships table. A user belongs to MANY tenants; each row is one * membership with a `role`. The active tenant lives on the Subject, but * the set of tenants a user MAY switch into is enumerated here. * * `[userId, tenantId]` is a composite UNIQUE — the DB enforces the * one-membership-per-(user, tenant) invariant that `addMembership` * upserts toward, and the unique constraint doubles as the BTREE index * backing the membership lookup + the dedup probe (so no separate * `.index([...])` on the same columns is needed). */ export declare const membershipsTable: TableLike; /** * Passkey ceremony challenges — the DataStore-backed `ChallengeStore` * (`dataStoreChallengeStore`) writes here so a multi-replica deployment's * register/assert ceremonies survive when `options` and `verify` land on * different replicas (the in-memory store is single-node only). Rows are * single-use + short-lived: `take` deletes on read, and `expiresAt` bounds * a challenge abandoned before verify. `key` is `:`. */ export declare const passkeyChallengesTable: TableLike; /** * Passkey (WebAuthn) credentials. One row per registered authenticator. * `publicKey` is the COSE public key (base64url). `counter` is the * authenticator's signature counter — the assertion handler rejects any * assertion whose counter does not strictly exceed the stored value * (cloned-authenticator detection). */ export declare const passkeysTable: TableLike; /** * MFA recovery (backup) codes. One row per code, stored HASHED (SHA-256, * same as auth tokens — never the plaintext). Minted at enrolment, shown * once, single-use: `consumedAt` is stamped the first time a code is * redeemed at sign-in as the authenticator-loss fallback. */ export declare const recoveryCodesTable: TableLike; /** * Sessions table. Active sessions enumerated server-side so apps can * implement "sign out other devices" + server-side revocation. * `handleSignIn` / `handleSignOut` do NOT write here (cookies are * self-describing HMAC-signed); apps that need device management * wire that up themselves. */ export declare const sessionsTable: TableLike; /** * Users table. `tenantId` is a plain text column (not a reference) * so the table can be added to apps that haven't yet declared their * own `tenants` table. Apps with a tenants store can layer a * referential constraint on top via the DB schema or DSL extensions. */ export declare const usersTable: TableLike; export { }