Package exports
Every function, class, and constant the Better IAM packages export, what each one does, and which guide explains it.
Most code reaches Better IAM through the betterIam() instance and its server API. The
packages also export standalone functions: the hooks, guards, and components of each framework integration,
policy helpers that run anywhere, verifiers for webhooks, assertions, and session tokens, and the building blocks
of custom integrations. This page lists every one of them by entry point, with what it does and the guide that
shows it in use. Types are not listed here: the ones you handle most are explained on
Types, and hovering a name in a code example shows its full type.
Each entry point is also available through the umbrella better-iam package; see
Installation for the subpath map.
@better-iam/a2a
Agent2Agent (A2A) support: IAM-attested agent cards, card verification and discovery, and authorization for A2A servers.
| Export | What it does | Explained in |
|---|---|---|
const A2A_ACCESS_DENIED | JSON-RPC error code (HTTP 403) of a message the caller may not send: error.data.reason says why (ACCESS_DENIED, UNKNOWN_SKILL, NO_RULE_FOR_CALLER, INSUFFICIENT_SCOPE). Tasks of other callers answer A2A's own -32001. | AI agents |
const A2A_CONFIRMATION_REQUESTED | JSON-RPC error code (HTTP 403) telling an agent that acts for a person that the person must confirm this request first: a confirmation request was filed (error.data.confirmationId, error.data.expiresAt); retry once approved. | AI agents |
const agentAttestationUri | The URI of the attestation extension Better IAM adds to every card it signs. | AI agents |
class AgentCardError | Why an agent card was refused by verifyAgentCard or discoverAgent: reason is unsigned, untrusted-key, signature, attestation, expired, issuer, tenant, endpoint, malformed or fetch. | AI agents |
createA2aAuthorizer(options) | Decisions shared by the gate and by handlers written with an A2A SDK. | AI agents |
createA2aGate(options) | The gate: gate(request, next) answers the request itself (the agent card, challenges, refusals) or passes it to next (the A2A server's handler) with the authenticated caller, recording who started each task on the way back. | AI agents |
createCardAttestor(options) | Keeps an agent's own card attested: returns a function that yields the signed card, signing on first use and again when the attestation nears its end. Concurrent calls share one signing request; when re-signing fails while the previous card is still valid, that card is returned. | AI agents |
createDelegationTokenCache(options) | For the agent side: returns a function yielding a current delegation token for an audience (and scopes), issuing one on first use and again when it nears its end, so an agent calling a service repeatedly does not ask for a token on every call. Concurrent calls for the same audience share one request. | AI agents |
class DelegationTokenError | Why verifyDelegationToken refused a token: reason is malformed, type, issuer, untrusted-key, signature, audience, tenant, expired, not-yet-valid, lifetime, replay or fetch. | AI agents |
discoverAgent(url, options) | Fetches a remote agent's card (url itself when it ends in .json, otherwise /.well-known/agent-card.json on its origin) and verifies it with verifyAgentCard, requiring the card's url to be on the origin it was fetched from. Call it only with agent addresses you chose: it makes an outbound request. | AI agents |
const handoffMetadataKey | The A2A message metadata key that carries a Better IAM hand-off (delegations.handoff) from the calling agent to the agent it calls, so the called agent can act for the same person with delegations.assume. | AI agents |
handoffOf(params) | The hand-off an A2A request carries (the called side): the delegation id in the message's metadata, else in the request's. Open a session for it with the called agent's own key (delegations.assume), which refuses hand-offs that are not this agent's. | AI agents |
memoryTaskOwners(options?) | In-memory owners: at most maxTasks entries (default 100000), each kept ttlMs (default seven days). | AI agents |
taskOwnerOf(caller) | The owner key of a caller: the same person through the same agent (or none), or the same OAuth client and subject. | AI agents |
verifyAgentCard(card, options) | Verifies that card was signed by a trusted Better IAM deployment and that its attestation is current: one of the card's signatures verifies over the canonical card (RFC 8785, without signatures) with a trusted key, the card carries exactly one attestation, it is neither expired nor from the future, and it matches issuers, tenantId and origin when given. | AI agents |
verifyDelegationToken(token, options) | Verifies a delegation token: a compact JWT of type biam-delegation+jwt, signed (EdDSA or ES256) by a key of the trusted issuer it names, for exactly audience (and tenantId), current, and issued for at most an hour. Returns who acts for whom; throws DelegationTokenError otherwise. | AI agents |
withHandoff(message, delegationId) | Adds a hand-off to an A2A message's metadata (the calling side). | AI agents |
@better-iam/adapter-libsql
libSQL / Turso storage adapter.
| Export | What it does | Explained in |
|---|---|---|
libsqlAdapter(options) | Stores Better IAM's data in libSQL: a local file (optionally encrypted), an embedded replica that syncs with a remote database, or a remote Turso or sqld database. Pass it as database to betterIam(). | Storage adapters |
@better-iam/adapter-postgres
PostgreSQL storage adapter.
| Export | What it does | Explained in |
|---|---|---|
postgresAdapter(options) | Stores Better IAM's data in PostgreSQL, the usual choice for production. Pass it as database to betterIam(). Transactions are serialized with a database advisory lock, so several application instances can share one database safely. | Storage adapters |
@better-iam/adapter-sqlite
SQLite storage adapter (better-sqlite3).
| Export | What it does | Explained in |
|---|---|---|
sqliteAdapter(options) | Stores Better IAM's data in a SQLite file (through better-sqlite3): the simplest setup, for development, tests, and single-server deployments. Pass it as database to betterIam(), and move to PostgreSQL when many processes write at once. | Storage adapters |
@better-iam/auth
Passwords, sessions, MFA, passkeys, magic links, recovery, and delivery templates.
| Export | What it does | Explained in |
|---|---|---|
class AuthService | The authentication service behind iam.auth: sign-in, sessions, account management, passwordless sign-in, MFA, and passkeys. betterIam() creates it; createAuth creates one on its own. | |
characterClasses(password) | Counts how many kinds of character a password uses (lowercase, uppercase, digits, and everything else), from 0 to 4, for password rules that require variety. | |
createAuth(options) | Creates the authentication service (sign-in, sessions, MFA, passkeys, and recovery) on its own, without the rest of the server. betterIam() creates one for you and exposes it as iam.auth, so you need this only to embed authentication in a custom host. | |
createMemoryRateLimiter(options?) | In-process limiter for single-instance deployments and tests. Counters are not shared between processes, and the map is bounded by maxKeys. | Security model |
createStoreRateLimiter(store) | The default limiter: durable counters in the IAM database, committed independently so rejected credentials cannot roll back their attempt. | |
const credentialTokenKinds | Maps each credential token type to the session kind it must resolve to (ses to user, key to api-key, rol to role, sts to session-token, dlg to delegated), so a token whose prefix disagrees with its stored session is refused. | |
const credentialTokenScanPattern | A regular expression source that matches Better IAM credential tokens in text. Add it to your secret scanner, log redaction, or pre-commit hook so leaked session tokens and API keys are caught before anyone uses them. | |
decryptSecret(value, secret, context?) | Opens a sealed value with the current secret or, during a rotation, a previous one. | |
encryptSecret(value, secret, context?) | Encrypts a value with the deployment secret (authenticated encryption), so stored factors and queued messages can be neither read nor altered without it. decryptSecret reverses it. | |
hashToken(token) | The SHA-256 hash, in hex, under which a token is stored and looked up. Storing only hashes means a database leak does not reveal usable session tokens or API keys. | |
isCommonPassword(password) | The built-in weak-password screen: common passwords, keyboard walks and sequences, and low variety. | |
newCredentialToken(type) | Creates a new typed credential token (biam_ses_…, biam_key_…, biam_rol_…, biam_sts_…, or biam_dlg_…) with a checksum at the end. | |
newId(prefix?) | Makes a new random record ID: the prefix you pass (default id), an underscore, and 22 random characters. IDs carry 128 random bits, so they cannot be guessed or enumerated. | |
newToken() | Makes a new random secret token (256 bits, base64url). Tokens are shown to their owner once; only their hash is stored. | |
openSecret(value, secrets, context?) | Opens a sealed value with the first of secrets that authenticates it, and says which one (0 is the current secret; higher indexes are previous ones kept during a rotation). Undefined when none does. | |
parseCredentialToken(value) | Recognizes a typed credential token and returns its type, or undefined when the shape or checksum is wrong, so a mistyped or truncated token can be refused before any database lookup. The type is only a routing hint: the stored session decides what a token is. | |
pwnedPasswords(options?) | A Have I Been Pwned "range" client (k-anonymity): hashes the password with SHA-1, sends only the first five hex characters, and matches the returned suffixes locally. Network failures accept the password unless failClosed. | Sign-in methods |
renderDeliveryMessage(message, options?) | Renders the messages Better IAM queues (verify-email, password-reset, email-change, magic-link, code, mfa-code, new-sign-in, sign-in-failures, certification-review, certification-reminder, delegation-request, delegation-confirmation, team-join-request, team-join-decided, team-review-requested, spend-alert, spend-anomaly, billing-statement, payment-reminder, owner-invitation, member-invitation) into a subject, plain text, and HTML, so a delivery callback can hand them to any provider. | Support and privacy |
@better-iam/auth/templates
| Export | What it does | Explained in |
|---|---|---|
renderDeliveryMessage(message, options?) | Renders the messages Better IAM queues (verify-email, password-reset, email-change, magic-link, code, mfa-code, new-sign-in, sign-in-failures, certification-review, certification-reminder, delegation-request, delegation-confirmation, team-join-request, team-join-decided, team-review-requested, spend-alert, spend-anomaly, billing-statement, payment-reminder, owner-invitation, member-invitation) into a subject, plain text, and HTML, so a delivery callback can hand them to any provider. | Support and privacy |
@better-iam/cli
The better-iam command line: migrations, bootstrap, audits, config as code, jobs.
| Export | What it does | Explained in |
|---|---|---|
const builtinCommands | Every built-in command, in help order. | |
class CliError | A command-line failure: an IamError (same code contract) that may carry a hint, printed on its own line by the better-iam binary, telling the person what to run or set next. | |
cliManifest() | The machine-readable description of every built-in command (what better-iam help --json prints), for docs and tools. | |
commandHelp(spec) | better-iam help <command>: usage, description, arguments, flags, and examples. | |
const configFileNames | Configuration file names the CLI looks for, in this order, in the working directory and then each parent. | |
configFromEnv(env?) | Deployment options from environment variables alone (twelve-factor style), for containers and CI jobs that have no configuration file: | |
createCli(options?) | Creates a better-iam-style program from code: the built-in commands plus your own (defineCommand), with the same parsing, help, configuration loading, and output. Use it to ship a project CLI, or to run commands in tests. | |
createProfileStore(env) | Opens the saved-session file that login, logout, profiles, and token commands use, located from env (see credentialsPath), so tools can list, save, or switch profiles the same way the CLI does. | |
credentialsPath(env) | Where saved sessions live: BETTER_IAM_CREDENTIALS, else %APPDATA%\better-iam\credentials.json on Windows, else $XDG_CONFIG_HOME/better-iam/credentials.json or ~/.config/better-iam/credentials.json. | |
defineCommand(spec) | Declares a CLI command with typed flags. Export an array of them as commands from better-iam.config.mjs to add project commands (seeding, reports, migrations of your own) that get the same flag parsing, help, configuration loading, and output formatting as the built-in ones. | |
findConfigFile(cwd) | The nearest configuration file in cwd or one of its parents, like Prettier and ESLint find theirs. | |
formatResult(value, format?, query?) | Turns a command result into the text printed on stdout. Strings are printed as they are. | |
lintTenantConfig(value) | Offline checks: the shape (validateTenantConfig) plus cross-references between the file's own items. | |
listRoutes(iam) | Every route the HTTP API serves for an instance, with whether it needs a credential. | |
loadConfig(options?) | Loads a configuration file and creates its instance: the same resolution the CLI uses, for scripts, workers, and tests that want better-iam.config.mjs without the command line. Close instance.store when done. | |
loadTenantConfig(path, context) | Reads a desired tenant configuration for config-plan / config-apply / config-validate: a .json file, or a JavaScript/TypeScript module whose default export is the configuration or a (possibly async) factory of it. | |
localTransport(iam, target, token?) | Calls API routes in process on a configured instance, as token (or with no credential), exposing exactly the routes and credential rules of the HTTP handler; what token commands use without --url. | |
main(argv?, cli?) | Runs the CLI like the better-iam binary: prints CODE: message (and a hint) on failure and resolves with the exit status, 0 on success, 2 for a usage mistake, 1 otherwise. For wrappers that ship their own binary. | Change safety |
processIO() | The process's own IO: stdout, stderr, process.env, and prompts when both stdin and stderr are terminals. | |
remoteTransport(url, token, fetcher?) | Calls API routes on a running IAM server over HTTP(S) with a bearer token, through the typed client (request IDs, one retry after a short rate limit); what token commands use with --url or a profile saved against a server. | |
runBinary(argv?, cli?) | What the better-iam binary does: runs main() on the process arguments, sets the exit status, and fails a command that can never finish instead of exiting 0. For packages that ship the CLI under their own bin. | |
runCli(argv, io?) | Runs the better-iam command-line tool with the given arguments, exactly as the better-iam binary does, so scripts and tests can call it in-process. It loads your configuration file as JavaScript, so point it only at trusted configuration. | |
selectPath(value, path) | Selects part of a result for --query: dotted keys (summary.create), array indexes (roles.0 or roles[0]), and [] to map over an array (findings[].kind). A missing key selects null rather than failing, like jq. | |
usageError(message, hint?) | A usage mistake (unknown flag, missing value, bad number): the binary exits with status 2 for these. |
@better-iam/client
Typed browser client with session store and passkey helpers.
| Export | What it does | Explained in |
|---|---|---|
class ClientError | Another name for IamClientError. | Typed client |
createIamClient(options?) | Creates the typed client for browsers and other services. Import your server instance as a type (createIamClient<typeof iam>()) and every API group, method, input, and result is typed, without bundling any server code. | Typed client |
class IamClientError | The error the typed client throws when the server refuses a call or the request fails. It carries the server's code and status, the wait before a retry for RATE_LIMITED, and the request ID, but never the raw response body. | Typed client |
@better-iam/client/passkeys
| Export | What it does | Explained in |
|---|---|---|
browserSupportsWebAuthn() | True when the browser supports passkeys (WebAuthn), so you can decide whether to offer them. | Typed client |
browserSupportsWebAuthnAutofill() | True when the browser can suggest passkeys in the username field's autofill, for a sign-in form without a separate passkey button. | Passkeys |
platformAuthenticatorIsAvailable() | True when the device has a built-in authenticator (Touch ID, Windows Hello, an Android fingerprint sensor), a good moment to suggest creating a passkey. | Typed client |
startAuthentication(options) | Asks the browser to sign in with a passkey, using the options your server returned. Send the result back to the server to finish signing in. | Passkeys |
startRegistration(options) | Asks the browser to create a passkey, using the options your server returned. Send the result back to the server to save it. | Typed client |
const WebAuthnAbortService | A service singleton to help ensure that only a single WebAuthn ceremony is active at a time. | Typed client |
@better-iam/client/session
| Export | What it does | Explained in |
|---|---|---|
createSessionStore(client, options?) | Framework-agnostic session state. The React and Vue bindings subscribe to it; it can also drive other frameworks or plain scripts. | Typed client |
isUnauthenticated(error) | True when an error means the caller is not signed in any more or must confirm who they are (the server answered 401 or 403). Anything else is a network or server failure, worth a retry rather than a sign-in page. | Typed client |
@better-iam/core
Models, the policy engine, the storage contract, the audit chain, and shared errors.
| Export | What it does | Explained in |
|---|---|---|
appendAuditEvent(tx, event) | Records an audit event at the end of its tenant's chain. Every audit insert must go through here. | |
applyMigrations(execute, dialect, options?) | Creates the schema and applies missing named migrations, recording each in iam_migrations. Run it inside the adapter's serialized write transaction. Returns the names applied now. | Adapters and plugins |
auditEventHash(event) | The hash of an event: SHA-256 over the canonical JSON of every field except hash itself. | |
const auditGenesis | The previousHash of the first event of every chain. | |
const authMethods | The sign-in methods a tenant policy can allow or restrict; impersonation is an administrative action, not a sign-in. | |
canonicalizeJson(value) | The JSON Canonicalization Scheme (RFC 8785): the single serialization of a JSON value that signers and verifiers agree on. Object members are sorted by the UTF-16 code units of their names at every depth, numbers use the ECMAScript shortest form and strings the escaping of JSON.stringify, and there is no whitespace. | |
canonicalJson(value) | Deterministic JSON: object keys sorted recursively, undefined properties omitted, arrays kept in order. | Audit chain |
chainAuditEvent(tx, event) | Assigns the next chain position to an event and advances the tenant's chain head. The caller stores the returned event; appendAuditEvent does both. Must run inside the transaction that records the event. | |
const COLLECTIONS_SQL | Distinct collection names in the records table. | |
compareIds(left, right) | Compares two IDs in the byte order databases use (SQLite's BINARY, PostgreSQL's "C" collation), so sorting in memory agrees with ORDER BY in SQL. | |
copyStore(source, target, options?) | Copies every record from source into an empty, migrated target (for example SQLite to PostgreSQL). Reads in one source transaction and writes in one target transaction, so the copy is consistent and all-or-nothing. | Storage adapters |
decodeJsonbDocument(data) | The original record JSON of a document written by encodeJsonbDocument. | |
definePolicy(document) | Writes a policy document in TypeScript, with type checking. It validates the document when your code loads, so a malformed policy fails at startup rather than when it is saved, and returns a detached copy. | Authorization |
delegationActor(chain) | The act claim for a chain of agents, the person's own delegate first and the agent acting now last. | |
const delegationTokenLimits | Lifetimes (seconds) and the longest chain of actors a delegation token carries. | |
const delegationTokenScopePattern | One scope a delegation token may carry: an action, or an action pattern whose only wildcard is *. | |
const delegationTokenType | The JWT typ header of delegation tokens: verifiers refuse any other. | |
describeRecords(execute, adapter, settings) | The adapter-independent part of IamStore.describe(): schema version, applied migrations, and record counts per collection. Missing tables read as empty, so an unmigrated database reports empty lists; any other failure rejects. | Adapters and plugins |
encodeJsonbDocument(data) | Record JSON as the PostgreSQL adapter stores it: valid jsonb, reversible by decodeJsonbDocument. | Database operations |
encodeLegacyPostgresRows(name, execute) | Migration hook for PostgreSQL: rewrites rows written before the value encoding existed, whose text jsonb would reject, so the jsonb index of 0002_query_indexes can be built. | |
evaluatePolicy(input) | Decides whether a request is allowed by a set of policy documents, with the same engine the server uses. It needs no database, so it runs anywhere (the playground uses it) and returns the decision, its reason, and the statements that matched. Grants add up; each boundary can only narrow them. | Policy documents |
const EXPIRY_FIELDS | Numeric fields SQL adapters index for findOrdered across a whole collection, so retention sweeps find expired and long-delivered records without scanning (0004_expiry_indexes). | |
exportStore(store, write, options?) | Writes a snapshot through write, one line at a time (without newlines). Runs in one store transaction, so the snapshot is consistent; that also holds the store's write lock until done. | Storage adapters |
findOrdered(store, collection, filter, order) | Records matching filter whose numeric order.field lies in [from, to], ordered by that field (ties by id, ascending) and paged. Uses the store's findOrdered when it has one and otherwise orders a plain find in memory. | Adapters and plugins |
class IamError | The error every Better IAM operation throws when it refuses a request. code is a stable name such as ACCESS_DENIED, status is the matching HTTP status, and message is for people. Check code in your own code; the error reference lists every code and how to handle it. | Adapters and plugins |
importStore(store, lines) | Loads a snapshot into an empty, migrated store in one transaction: a malformed line, a record the store refuses, or a missing or mismatched trailer rolls everything back. | Storage adapters |
const INDEXED_FIELDS | High-cardinality string fields looked up across tenants or inside large collections (sessions, identities, memberships, bindings, protocol artifacts, delivery queues). SQL adapters may index them; the list only affects performance, never results. | Database operations |
instrumentStore(store, onCall, now?) | Wraps a store so every data call is reported to onCall (reads, writes, collections, and describe; transaction, migrate, and close pass straight through), for slow-query logging, capacity planning, and tests that bound how much work an operation does. | Database operations |
ipCounterKey(address) | The key a per-address counter uses for a client: an IPv4 address as itself (the IPv4-mapped IPv6 form folded to it), an IPv6 address as its /64 (2001:db8:1:2::/64), since one subscriber or host normally controls a whole /64 and can rotate through it at will. | |
ipMatches(address, network) | True when address lies inside network (an address or CIDR block of the same family). An IPv4-mapped IPv6 address (::ffff:198.51.100.7) matches the IPv4 networks that contain its IPv4 address, and an IPv4 address the IPv4-mapped networks (::ffff:198.51.100.0/120) that contain it. | |
isIpRange(value) | True for an IPv4/IPv6 address or CIDR block, as accepted by the IpAddress operator. | |
isMissingTable(error) | A query failed because a table does not exist (PostgreSQL 42P01, SQLite "no such table"). | |
const JSONB_ESCAPE_KEY | Reserved object key of the PostgreSQL value encoding (encodeJsonbDocument), which stores strings jsonb cannot hold. Filters whose objects use it are evaluated in memory. | |
const LOOKUP_INDEX_STEPS | The lookup fields each schema step indexes (SQLite and libSQL; PostgreSQL's document index covers every field). A released step never changes: new fields get a new step. | |
matchesFilter(record, filter) | The in-memory definition of filter semantics. Drivers' SQL must agree with it. | |
matchPattern(pattern, value, context?) | Tests whether an action or resource name matches a policy pattern, exactly as policy evaluation does. The whole name must match; * matches any run of characters (including / and :) and ? exactly one, and ${...} variables are filled in from the optional context first. There are no regular expressions. | |
const MAX_QUERY_CONDITIONS | Most typed conditions planQuery hands to a driver; further keys are filtered in memory. | Adapters and plugins |
const ORDERED_FIELDS | Numeric fields SQL adapters index for findOrdered within a tenant (audit time and sequence). | |
planQuery(collection, filter, capabilities?) | Splits a validated filter into driver conditions and keys left to the in-memory filter. | Adapters and plugins |
postgresSelect(query) | SELECT for PostgreSQL. Scalar tests share one jsonb containment test, served by a GIN index. | Adapters and plugins |
const QUERYABLE_FIELD | Field names a driver may inline into SQL paths. Other names are filtered in memory. | |
readDelegationTokenClaims(claims, expected) | Checks the claims of a (signature-verified) delegation token against what the verifier expects: well formed, from an accepted issuer, for exactly this audience (and tenant), current within the clock tolerance, and issued for at most delegationTokenLimits.maxSeconds. | |
class RecordStore | The base class the reference storage adapters share. It implements the storage contract over one records table, so SQLite, libSQL, and PostgreSQL behave identically; extend it to support another SQL database. | Adapters and plugins |
resolvePolicyValue(value, context) | Resolves the variables of a string condition value. Returns undefined when any variable is unresolved. | |
schemaMigrations(dialect) | The schema steps for one SQL dialect, in order. applyMigrations runs the ones a database has not applied yet. | |
const SNAPSHOT_FORMAT | Portable store snapshots: every record of every collection as JSON Lines, independent of the adapter, for backups, moving from SQLite to PostgreSQL, and test fixtures. Records are copied verbatim, so audit hash chains, token hashes, and encrypted secrets stay valid. | |
const SNAPSHOT_VERSION | The version of the snapshot format that better-iam store-export writes. store-import accepts only this version, so a snapshot in another format is refused before anything is written. | |
sqliteSelect(query) | SELECT for SQLite and libSQL (JSON1). json conditions are not supported. | Adapters and plugins |
storableString(value) | True when the string has no U+0000 and no unpaired surrogate. Such strings can be stored as record values, but database text comparisons cannot represent them, so find evaluates filters holding them in memory. Identifiers must satisfy it. | |
storageError(error) | Turns a database failure into an IamError that is safe to show: a unique-key clash becomes CONFLICT (409), a busy or deadlocked database STORAGE_BUSY (503, retry the whole operation), and no message reveals SQL or record data. | |
summarizeStoreCalls(calls) | Totals of a list of calls, grouped by method and collection (find:sessions). | |
tenantTreeActive(store, tenantId) | Walks a tenant and its ancestors: true only when every one exists and is active. Cycles read as inactive. | |
validatePolicy(value) | Checks that a value is a well-formed policy document and throws INVALID_POLICY describing the first problem. The server runs it before storing a document and again before evaluating one. | |
validPolicyVariables(value) | Every ${...} in a value must be a well-formed variable reference. | |
verifyAuditChain(events, options?) | Verifies a run of events from one tenant: contiguous sequences, each previousHash equal to the previous event's hash (or previousHash of the first event when the run starts mid-chain), and every hash recomputable. Events are sorted by sequence first, so exports and database reads can be passed as they come. | Audit chain |
@better-iam/core/conformance
| Export | What it does | Explained in |
|---|---|---|
adapterConformanceCases() | A fresh copy of every conformance case, in a stable order. | Adapters and plugins |
class ConformanceFailure | The error the storage conformance suite throws when an adapter behaves differently from the reference adapters. Its message names the failing check, so a custom adapter's test run shows exactly what to fix. | |
runAdapterConformance(createStore) | Runs every case against fresh stores and collects failures instead of stopping at the first. | Adapters and plugins |
@better-iam/mcp
Tool-level authorization for Model Context Protocol servers: Better IAM credentials, agents and OAuth tokens.
| Export | What it does | Explained in |
|---|---|---|
createMcpAuthorizer(options) | The tool-level decisions of createMcpGate without the HTTP handling, for tool handlers written directly against an MCP SDK: authenticate(request) identifies the caller, canCall(caller, name, args) decides one tool call, and visibleTools(caller, tools) filters a tool list. | AI agents |
createMcpGate(options) | Puts Better IAM in front of a Model Context Protocol server that speaks Streamable HTTP and decides, tool by tool, who may see and call what. | AI agents |
protectedResourceMetadataUrl(resource) | Where RFC 9728 metadata lives for a resource: /.well-known/oauth-protected-resource + the resource path. | Dynamic registration and MCP |
@better-iam/middleware
Framework-neutral middleware core with Express, Hono, and Fastify adapters.
| Export | What it does | Explained in |
|---|---|---|
checkRequestOrigin(request, trustedOrigins?) | The CSRF boundary for application routes: a state-changing request authenticated by the session cookie (no Authorization header) must come from this application's origin, the IAM origin, or a trusted origin. | Express, Hono, and Fastify |
checkStepUp(session, requirement, now?) | Checks a session against a step-up requirement; null when it qualifies. Accepts the getSession result or its inner session record. Impersonated sessions always fail a recency requirement, as the server's own check does. | Frameworks |
createRequestHelpers(resolveIam, binding, options?) | Builds the per-request helpers over a framework's request and response. Framework adapters call this once per request. | Express, Hono, and Fastify |
enforceGuard(helpers, request, spec?, origin?) | Runs a guard; resolves with the session or throws the refusal (IamRequestError or the server's IamError). With origin, a cookie-authenticated unsafe request from an untrusted origin is refused first. | Express, Hono, and Fastify |
errorBody(error) | The IAM API's JSON error envelope, used by every adapter for refusals. | Express, Hono, and Fastify |
errorCode(error) | Reads the code of an error (such as ACCESS_DENIED) without assuming it is an IamError; undefined for anything else. Useful in your own error handlers, where the thrown value can be anything. | Express, Hono, and Fastify |
errorStatus(error) | Reads the HTTP status of an error without assuming it is an IamError; undefined for anything else. | Express, Hono, and Fastify |
class IamRequestError | A refusal raised by the request helpers and guards, with the IAM code and HTTP status. reason is set for step-up failures (mfa, recent, impersonation). Framework adapters turn it into the IAM JSON error envelope or, for page navigations, a redirect to the login / step-up page. | Express, Hono, and Fastify |
isAuthenticationError(error) | True for the errors getSession raises when there is no usable session. | Express, Hono, and Fastify |
isIamRefusal(error) | True for any error carrying an IAM code and an HTTP status (server IamError, client errors, IamRequestError). | Express, Hono, and Fastify |
nodeHeaders(record) | Converts a Node IncomingMessage-style header record into Headers. | Express, Hono, and Fastify |
parseCookieHeader(header) | Splits a Cookie header into name/value pairs (values left encoded). | Express, Hono, and Fastify |
refusalResponse(error, request, pages) | How a guard should answer a refusal: a redirect for page navigations when a page is configured, else JSON. | Express, Hono, and Fastify |
safeRedirectPath(value, fallback?) | A same-site relative path safe to redirect to, or fallback. Refuses schemes, //host, and backslash tricks. | Express, Hono, and Fastify |
setCookieSummary(header, now?) | The name, raw value, and whether a Set-Cookie header deletes the cookie (Max-Age=0 or a past Expires). | Express, Hono, and Fastify |
tenantOf(session) | The tenant a session acts in. | Express, Hono, and Fastify |
underPath(pathname, prefix) | True when pathname is prefix or below it on a segment boundary. | Express, Hono, and Fastify |
withQuery(target, params) | Appends query parameters, skipping undefined values. | Express, Hono, and Fastify |
@better-iam/middleware/express
| Export | What it does | Explained in |
|---|---|---|
createIamExpress(source, options?) | Express / Connect integration. middleware serves the IAM API (through iam.nodeHandler, so node protocol mounts such as the OAuth provider work) and gives every other request req.iam; requireSession and authorize are route guards; errorHandler answers IAM refusals thrown by your routes. | Express, Hono, and Fastify |
@better-iam/middleware/fastify
| Export | What it does | Explained in |
|---|---|---|
createIamFastify(source, options?) | Fastify integration. plugin (register it with app.register(iamFastify.plugin)) answers the IAM API in an onRequest hook, before Fastify parses bodies, through iam.nodeHandler; every other request gets request.iam. | Express, Hono, and Fastify |
@better-iam/middleware/hono
| Export | What it does | Explained in |
|---|---|---|
createIamHono(source, options?) | Hono integration (Node, Bun, Deno, Workers). middleware answers the IAM API with iam.handler and sets c.get('iam') for every other request; requireSession and authorize are route guards; onError turns IAM refusals thrown by handlers into the JSON error envelope. | Express, Hono, and Fastify |
@better-iam/nestjs
NestJS module, guard, decorators, and testing utilities.
| Export | What it does | Explained in |
|---|---|---|
AssertionClaims(...dataOrPipes) | The verified assertion claims (sub, tid, roles, groups, ext, ...), or null on a @Public() handler. | NestJS |
Authorize(action, options?) | Enforces action before the handler runs. Rules accumulate: every @Authorize on the class and the method must allow. The resource defaults to the tenant itself (iam/{tenantId}) and the tenant to the module's resolver. | NestJS |
createIamRequestHandler(iam) | A Node request handler that serves the IAM HTTP API (and mounted OAuth/SAML/SCIM protocols) from inside a Nest application, for app.use('/api/iam', createIamRequestHandler(iam)) or the module's mount option. It works with bodies already consumed by Nest's parsers. | NestJS |
credentialOf(request) | Turns a Nest request into the { headers } credential that iam.api calls expect, so your own services can call the API as the person making the request. | NestJS |
Credentials(...kinds) | Restricts which credential kinds may call the handler, e.g. @Credentials('api-key') for machine endpoints. | NestJS |
CurrentIdentity(...dataOrPipes) | The caller's identity, or null on a @Public() handler called without a credential. | NestJS |
CurrentPrincipal(...dataOrPipes) | The authenticated { identity, session }, or null on a @Public() handler called without a credential. | Frameworks |
CurrentSession(...dataOrPipes) | The caller's session record, or null on a @Public() handler called without a credential. | NestJS |
FilterAccessible(action, options) | Drops items the caller may not perform action on from a list response, using the reverse query listAccessible over the registered resources of a managed type (one query per page of 1000, never one decision per item, so the audit log is not flooded with denials). | NestJS |
const IAM_ASSERTION_OPTIONS | Injection token for the resolved IamAssertionOptions. | NestJS |
const IAM_INSTANCE | Injection token for the betterIam() instance. | NestJS |
const IAM_OPTIONS | Injection token for the resolved IamModuleOptions. | NestJS |
class IamAssertionGuard | For downstream services that receive stateless assertions from a Better IAM deployment: verifies the token without a database or network round trip and exposes its claims. It never contacts the IAM server, so revocation takes effect when the (short-lived) assertion expires. | NestJS |
class IamAssertionModule | Configures IamAssertionGuard for a service that trusts assertions from a Better IAM deployment. | NestJS |
class IamEventsExplorer | Subscribes every @OnIamEvent provider method to the IAM event stream at bootstrap and, when dispatchIntervalMs is set, drives iam.events.dispatch() until shutdown. | NestJS |
class IamExceptionFilter | Renders IamErrors thrown from handlers and providers (for example IamService.require or direct iam.api.* calls) as the IAM server's { error: { code, message } } body with the error's status instead of a 500. | NestJS |
class IamFilterInterceptor | The interceptor behind @FilterAccessible: it removes items the caller may not act on from a list response. You apply it through the decorator rather than directly. | NestJS |
class IamGuard | Authenticates every request it guards and enforces the handler's metadata: @Public(), @Credentials(), @RequireMfa(), and @Authorize() rules. Failures render as the IAM server's { error: { code, message } } body with its status (401 unauthenticated, 403 denied, 429 rate limited). | NestJS |
class IamHttpMiddleware | Nest middleware form of createIamRequestHandler, registered by IamModule.forRoot({ mount: true }). | NestJS |
class IamModule | Better IAM for NestJS: provides IamService, IamGuard, and the exception filter; optionally installs the guard globally, mounts the IAM HTTP API, and binds @OnIamEvent handlers. | NestJS |
class IamService | Request-scoped IAM calls for controllers and providers: every method takes the incoming request (Express, Fastify, or anything with headers) and forwards its credential, so decisions are always made for the actual caller. | NestJS |
isAuthenticationError(error) | True for the errors authentication raises when a request carries no usable credential. | NestJS |
isIamError(error) | True when an error is an IamError. It checks the shape rather than the class, so errors from a second copy of @better-iam/core in node_modules are recognized too. | NestJS |
OnIamEvent(pattern) | Subscribes a provider method to audit events whose action matches the pattern(s), e.g. identity:*. Delivery is post-commit and at-least-once, driven by iam.events.dispatch() (see IamModule's dispatchIntervalMs). | NestJS |
Public() | Skips the session requirement; the guard still resolves a principal when a credential is present. | NestJS |
RequireClaims(requirements) | Requirements the verified assertion must meet in addition to signature, audience, and lifetime. | NestJS |
RequireMfa() | Requires a session that completed multi-factor authentication (user sessions only). | NestJS |
TenantId(...dataOrPipes) | The tenant the request's @Authorize rules were evaluated in (or the session tenant when there were none). | NestJS |
toHttpException(error) | The HTTP exception Nest renders for an IAM error: the server's own { error: { code, message } } body and status. | NestJS |
@better-iam/nestjs/testing
| Export | What it does | Explained in |
|---|---|---|
createTestingIam(options?) | An in-memory stand-in for a betterIam() instance for unit and e2e tests of Nest applications: no database, no password hashing, principals chosen by bearer token, and decisions made by a callback. | NestJS |
@better-iam/next
Next.js App Router helpers: guarded pages, routes, actions, and edge checks.
| Export | What it does | Explained in |
|---|---|---|
class AssertionError | Raised by the edge verifiers; code and status match the server's IamError for the same failure. | Next.js |
const authFields | Form field names shared by the actions and the client forms. intent selects the step a submission performs. | Next.js |
authHiddenFields(state) | The hidden inputs a form renders for state so its next submission continues the flow: next, the pending challenge on the MFA and enrollment steps, the email and organization on the steps after the credentials, and the "keep me signed in" choice (after the credentials step, which renders its own checkbox). | Next.js |
const authStepFields | Hidden fields the MFA and enrollment steps post back besides tenantId, challenge, next, and keepSignedIn, so a refused code re-renders the same step without client JavaScript. authHiddenFields(state) lists them all. | Next.js |
checkStepUp(session, requirement, now?) | Checks a session against a step-up requirement; null when it qualifies. Accepts the getSession result, its inner session record, or an apiRoute principal. | Advanced |
createAuthActions(host, options?) | Headless server actions for sign-in, MFA, passwordless codes, password reset, sign-up, email verification, invitations, step-up, and sign-out. Pass createIamNext()'s result; the actions call the IAM handler in process, so session cookies are written through cookies() and forms work without client JavaScript. | Next.js |
createBackground(resolve, options?) | Background delivery and maintenance for a Better IAM instance in Next.js. Call background.schedule() after actions that queue email (sign-up, password reset, invitations) so it goes out after the response, and mount background.cron() for periodic jobs and as a safety net when after() cannot run. | Next.js |
createIamMiddleware(options) | Edge-safe presence check for the session cookie: signed-out visitors are redirected before a protected page renders. It is a routing convenience, not authorization; pages still call requireSession or require. | Next.js |
createIamNext(source, options?) | Server-side helpers for the App Router. Server components and route handlers read the session from the request cookies, enforce with require, batch advisory decisions with can, and mount the IAM handler with handlers(). | Next.js |
createWebhookHandler(options) | A route handler that receives Better IAM webhooks: export const POST = createWebhookHandler({ secret, onEvent }). Unsigned, stale, or oversized requests answer 401/413 without calling onEvent; a throwing onEvent answers 500 so the sender retries with backoff. | Advanced |
isAuthenticationError(error) | True for the errors getSession raises when there is no usable session. | Next.js |
isNextControlError(error) | True for Next's control-flow throws (redirect, notFound, forbidden, unauthorized), which must propagate. | Next.js |
matchPath(pattern, pathname) | Glob over URL paths: * matches within one segment, ** across segments. | Next.js |
parseSetCookie(header) | Parses one Set-Cookie header into the name, decoded value, and options Next's cookies().set accepts. | Next.js |
const pathnameHeader | The request header middleware forwards so server components know the path being rendered. | Next.js |
safeRedirectPath(value, fallback?) | A same-origin path safe to redirect to after sign-in, or fallback. Rejects absolute URLs, protocol-relative //host, backslash tricks, and control characters, so a ?next= parameter cannot become an open redirect. | Middleware |
sessionCookieName(secure) | The cookie name the server issues: host-prefixed on HTTPS, plain on loopback development. | Next.js |
verifyAssertionToken(token, options) | Verifies an assertion issued by assertions.issue with Web Crypto, so middleware and edge handlers can trust it without a database. Same rules as the server's verifyAssertion: HS256 only, audience, optional issuer, and time. | Advanced |
verifyWebhook(input) | Checks an X-Better-IAM-Signature header (v1=<hex HMAC-SHA256 of "{timestamp}.{body}">) with Web Crypto. Equivalent to the server's verifyWebhookSignature, for edge runtimes. | Next.js |
withAssertion(options, handler) | Route handler guard for services that receive assertions from a Better IAM application: the bearer token is verified offline and its claims passed to the handler. Failures answer 401 with the server's error envelope. | Advanced |
@better-iam/next/client
| Export | What it does | Explained in |
|---|---|---|
Can(props) | Renders children only when the advisory decision allows the action; fallback otherwise and loading meanwhile. Re-exported from @better-iam/react. | Frameworks |
IamNextProvider(props) | IamProvider for the App Router: pass initialSession from iamNext.sessionForClient() in a server layout, and server components refresh automatically when the session changes on the client. | Next.js |
InvitationForm(props) | Accepts an invitation with a name and a new password, then enrolls or verifies the second factor when the organization requires one, and shows the recovery codes. | Next.js |
InvitationFormView(props) | The markup of InvitationForm for a given action state. | |
PasswordResetForm(props) | Sets a new password from a reset link. Existing sessions end; the person signs in again. | Server actions and forms |
PasswordResetFormView(props) | The markup of PasswordResetForm for a given action state. | |
PasswordResetRequestForm(props) | Asks for a password reset email. The reply never reveals whether the account exists. | Server actions and forms |
PasswordResetRequestFormView(props) | The markup of PasswordResetRequestForm for a given action state. | |
ReauthenticateForm(props) | Confirms the signed-in person's password, then their second factor when the account has one. The confirmation issues a new session, whose cookie follows keepSignedIn. | Server actions and forms |
ReauthenticateFormView(props) | The markup of ReauthenticateForm for a given action state. | Server actions and forms |
SignInForm(props) | Password sign-in with an optional emailed sign-in code, then the second factor (authenticator, emailed code, or recovery code) or first-time authenticator enrollment, as action directs. Works without client JavaScript. | Organizations in the URL |
SignInFormView(props) | The markup of SignInForm for a given action state. | Server actions and forms |
SignUpForm(props) | Self-registration: name, email, and password, usually followed by an email to confirm the address. | Next.js |
SignUpFormView(props) | The markup of SignUpForm for a given action state. | |
useAccessible(options) | The registered resources of a managed type the signed-in principal may act on; refetched when the input or identity changes. Re-exported from @better-iam/react. | Next.js |
useAuthorize(options) | Batched advisory decisions for rendering menus and buttons. Re-evaluated when the checks or the signed-in identity change; the server still enforces every operation. Re-exported from @better-iam/react. | Frameworks |
useIamClient() | The client passed to the provider, typed as the caller declares it. Re-exported from @better-iam/react. | Next.js |
useRouterSync() | Calls router.refresh() whenever the signed-in identity changes in the client (sign-in, sign-out, account switch, or a session that expired while the tab was open), so server components re-render with the new cookies. | Next.js |
useSession() | The current session snapshot plus refresh, sign-out, and manual replacement (after a sign-in response). Re-exported from @better-iam/react. | Next.js |
useSignOut(options?) | Signs out through the client session store, then navigates (when redirectTo is given) and refreshes server components so no page keeps rendering the previous session. | Advanced |
@better-iam/next/edge
| Export | What it does | Explained in |
|---|---|---|
class AssertionError | Raised by the edge verifiers; code and status match the server's IamError for the same failure. | Next.js |
createIamMiddleware(options) | Edge-safe presence check for the session cookie: signed-out visitors are redirected before a protected page renders. It is a routing convenience, not authorization; pages still call requireSession or require. | Next.js |
createWebhookHandler(options) | A route handler that receives Better IAM webhooks: export const POST = createWebhookHandler({ secret, onEvent }). Unsigned, stale, or oversized requests answer 401/413 without calling onEvent; a throwing onEvent answers 500 so the sender retries with backoff. | Advanced |
matchPath(pattern, pathname) | Glob over URL paths: * matches within one segment, ** across segments. | Next.js |
const pathnameHeader | The request header middleware forwards so server components know the path being rendered. | Next.js |
safeRedirectPath(value, fallback?) | A same-origin path safe to redirect to after sign-in, or fallback. Rejects absolute URLs, protocol-relative //host, backslash tricks, and control characters, so a ?next= parameter cannot become an open redirect. | Middleware |
sessionCookieName(secure) | The cookie name the server issues: host-prefixed on HTTPS, plain on loopback development. | Next.js |
verifyAssertionToken(token, options) | Verifies an assertion issued by assertions.issue with Web Crypto, so middleware and edge handlers can trust it without a database. Same rules as the server's verifyAssertion: HS256 only, audience, optional issuer, and time. | Advanced |
verifyWebhook(input) | Checks an X-Better-IAM-Signature header (v1=<hex HMAC-SHA256 of "{timestamp}.{body}">) with Web Crypto. Equivalent to the server's verifyWebhookSignature, for edge runtimes. | Next.js |
withAssertion(options, handler) | Route handler guard for services that receive assertions from a Better IAM application: the bearer token is verified offline and its claims passed to the handler. Failures answer 401 with the server's error envelope. | Advanced |
@better-iam/nuxt
Nuxt module and h3 helpers.
| Export | What it does | Explained in |
|---|---|---|
export default | The Nuxt module. Add '@better-iam/nuxt' to modules in nuxt.config.ts: it mounts the IAM API in Nitro, installs the Vue bindings with the session loaded during server rendering, and guards pages. | Nuxt |
@better-iam/nuxt/h3
| Export | What it does | Explained in |
|---|---|---|
createIamH3(source, options?) | Server helpers for h3 and Nitro (Nuxt server routes, standalone Nitro, or h3 apps): read the session from the request cookies, enforce before handling, batch advisory decisions, and mount the IAM handler. Sessions are memoized per event. | Nuxt |
eventHeaders(event) | The request headers of an h3 v1 or v2 event. | Nuxt |
eventRequest(event) | A Web request for an h3 v1 or v2 event; the Node fallback buffers the body, so call it before anything reads it. | Nuxt |
class IamH3Error | An error h3 understands in both majors (statusCode for v1, status for v2); data.code carries the IAM code. | Nuxt |
isAuthenticationError(error) | True for the errors getSession raises when there is no usable session. | Nuxt |
@better-iam/oauth
OAuth/OIDC authorization server, resource-server helpers, and Shared Signals.
| Export | What it does | Explained in |
|---|---|---|
createAccessTokenVerifier(options) | Offline verification of JWT access tokens issued for a resource server (RFC 9068), including DPoP proof of possession (RFC 9449) with in-memory proof replay detection. Opaque tokens need the provider's introspection. | Resource servers and tokens |
createOAuthLogin(config) | Creates the "sign in with Google, GitHub, Microsoft, or your company's provider" flows: it sends people to an OAuth or OpenID Connect provider and signs them in when they come back. Attach it with iam.useProtocol(...). | OAuth and OIDC sign-in |
createOAuthProvider(config) | Turns Better IAM into an OAuth 2.0 and OpenID Connect provider, so your other applications and MCP servers can sign people in with their account here and receive access tokens. | OAuth/OIDC provider |
createProtectedResourceHandler(options) | Serves the metadata document at its well-known path (GET, HEAD, and CORS preflight, readable from any origin); returns undefined for every other request so it can sit in front of the API's own routing. | Dynamic registration and MCP |
createProviderAdapter(store, encodedKey, validateSession?, registerClient?) | Provider persistence with encrypted payloads and hashed token identifiers. Every artifact is bound to the tenant of its client and account, and every user grant is re-validated against its IAM session on each use. | |
createResourceGuard(options) | Everything an API (such as an MCP server) needs in front of its routes: it serves the RFC 9728 metadata document, verifies bearer or DPoP access tokens, and answers failures with 401/403 and a WWW-Authenticate challenge that names the metadata URL, so OAuth clients can discover the authorization server and try again. | Dynamic registration and MCP |
createSharedSignalsTransmitter(config) | An OpenID Shared Signals Framework transmitter: turns IAM audit events (sessions revoked, credentials changed, identifiers changed, accounts disabled or deleted) into signed Security Event Tokens (RFC 8417) with CAEP and RISC event types, and pushes them to each tenant's receivers (RFC 8935) with retries. | Shared Signals |
protectedResourceMetadata(options) | The metadata document (RFC 9728 §2) clients fetch to find the authorization server for an API. | Dynamic registration and MCP |
protectedResourceMetadataUrl(resource) | Where the metadata lives: /.well-known/oauth-protected-resource inserted before the resource's path. | Dynamic registration and MCP |
const sharedSignalEvents | Security event types the transmitter emits (CAEP and RISC). | Shared Signals |
@better-iam/projects
Reference tenant-scoped Projects plugin.
| Export | What it does | Explained in |
|---|---|---|
createProjectsPlugin() | Reference plugin providing tenant-scoped project records. | Adapters and plugins |
@better-iam/react
React provider, hooks, and permission-gated components.
| Export | What it does | Explained in |
|---|---|---|
Can(props) | Renders children only when the advisory decision allows the action; fallback otherwise and loading meanwhile. | React |
createSessionStore(client, options?) | Framework-agnostic session state. The React and Vue bindings subscribe to it; it can also drive other frameworks or plain scripts. Re-exported from @better-iam/client. | React |
IamProvider(props) | Holds the typed client and one session store for the tree below. Create the client once, outside render. | React |
isUnauthenticated(error) | True when an error means the caller is not signed in any more or must confirm who they are (the server answered 401 or 403). Anything else is a network or server failure, worth a retry rather than a sign-in page. Re-exported from @better-iam/client. | React |
useAccessible(options) | The registered resources of a managed type the signed-in principal may act on; refetched when the input or identity changes. | Batches and reverse queries |
useAccessPaths(options) | For an action the signed-in person may be denied: whether they are allowed and, if not, the self-service paths (step up to MFA, accept terms, activate an eligible role, request a package) that would allow them. | Access paths |
useAgentCatalog(options) | The agents the signed-in person may delegate to, with their purpose, model and sponsor (agents.catalog). | AI agents |
useAgreements(options) | The signed-in person's terms of use and a way to accept them; policies can hold back access until they do. | React |
useAuthorize(options) | Batched advisory decisions for rendering menus and buttons. Re-evaluated when the checks or the signed-in identity change; the server still enforces every operation. | Batches and reverse queries |
useConfirmations(options) | The actions AI agents acting for the signed-in person asked them to confirm (delegations with confirm), to answer from a notification or an inbox. An approval opens exactly that action on that resource for a few minutes. | AI agents |
useDelegations(options) | The AI agents acting (or asking to act) for the signed-in person, and the actions to manage them. Granting and approving need a recent sign-in (RECENT_AUTH_REQUIRED otherwise). Agents never get more than the person has. | AI agents |
useFeatureFlag(options) | Whether one feature flag is on for the tenant; value is false until it has loaded. | Feature flags |
useFeatureFlags(options) | The tenant's feature flags for the signed-in session, to show or hide UI. keys limits the request to those flags. Hiding UI is not enforcement: gate the server side with iam.features or a tenant.features condition. | Feature flags |
useIamClient() | The client passed to the provider, typed as the caller declares it. | React |
useModels(options) | The AI models the signed-in caller may use now (inference.listMine), for a model picker. | AI agents |
useMySpend(options) | The signed-in person's own spend (billing.mySpend): what their usage and their agents' cost this month (or period), grouped by meter (default), day, agent, tenant or tag:{name}, with a projection and their budgets. | Billing and spend |
useSession() | The current session snapshot plus refresh, sign-out, and manual replacement (after a sign-in response). | React |
useSpendCheck(options) | Whether the signed-in caller's usage (of meter, when given) is within every enforced spend budget that covers it (billing.check), to warn before a costly action. allowed is true until the answer arrives; the server still refuses usage recorded with enforceBudgets. | Billing and spend |
useTeams(options) | The signed-in person's teams with self-service joining and leaving (teams.listMine, requestToJoin, leave). |
@better-iam/react-router
React Router (framework mode) middleware, guarded loaders, and actions.
| Export | What it does | Explained in |
|---|---|---|
checkRequestOrigin(request, trustedOrigins?) | The CSRF boundary for application routes: a state-changing request authenticated by the session cookie (no Authorization header) must come from this application's origin, the IAM origin, or a trusted origin. Re-exported from @better-iam/middleware. | Frameworks |
checkStepUp(session, requirement, now?) | Checks a session against a step-up requirement; null when it qualifies. Accepts the getSession result or its inner session record. Impersonated sessions always fail a recency requirement, as the server's own check does. Re-exported from @better-iam/middleware. | Frameworks |
createIamRouter(source, options?) | React Router (framework mode, v7.9+ / v8) integration. middleware goes on the root route and gives every loader and action iamRouter.helpers(args); cookies the in-process client receives are added to the response. api is the loader and action of an api/iam/* resource route. | React Router |
isAuthenticationError(error) | True for the errors getSession raises when there is no usable session. Re-exported from @better-iam/middleware. | React Router |
safeRedirectPath(value, fallback?) | A same-site relative path safe to redirect to, or fallback. Refuses schemes, //host, and backslash tricks. Re-exported from @better-iam/middleware. | React Router |
@better-iam/saml
SAML 2.0 service provider with tenant-managed connections.
| Export | What it does | Explained in |
|---|---|---|
certificateInfo(pem) | Reads an identity provider's PEM certificate and returns its SHA-256 fingerprint, subject, and validity dates, so an administration screen can show which certificate is configured and when it expires. | |
createSamlCache(store, tenantId, connectionId, expectedRequestId?) | Remembers which SAML responses were already used, in the IAM database, so a captured response cannot be replayed. The SAML service creates it for you. | |
createSamlService(config) | Creates the SAML service provider: the metadata, sign-in, and assertion endpoints that let organizations sign in with their own identity provider. Attach it with iam.useProtocol(...); see SAML. | SAML |
normalizeCertificate(value) | Normalizes a PEM or bare base64 DER certificate to PEM, rejecting anything that is not a parseable X.509 certificate. | |
parseIdpMetadata(xml) | Reads entity ID, redirect-binding SSO/SLO endpoints, and signing certificates from IdP metadata. The document must describe exactly one identity provider; DTDs and entities are refused. | SAML |
validateSamlEnvelope(xml, callbackUrl, expectedRequestId, encryptedRequired?) | Supplements Node-SAML's cryptographic checks with exact response destination checks. expectedRequestId: null validates an IdP-initiated response, which must not answer any request. |
@better-iam/scim
SCIM 2.0 inbound provisioning and outbound provisioning to applications.
| Export | What it does | Explained in |
|---|---|---|
createScimProvisioner(config) | Outbound SCIM 2.0 provisioning: keeps downstream applications' user directories in step with a tenant's members. | SCIM outbound |
createScimService(config) | SCIM 2.0 provisioning server: connection-scoped bearer tokens, Users and Groups with RFC 7644 filtering, sorting, attribute projection, /.search, PATCH value paths, /Bulk, ETags and pagination, and explicit administrator-controlled group-to-role mappings. | Federation |
parseScimFilter(filter) | Parses a filter into a predicate over rendered SCIM resources; an absent filter matches everything. |
@better-iam/server
The betterIam() factory: tenants, identities, authorization, governance, HTTP API.
| Export | What it does | Explained in |
|---|---|---|
actsInOwnRight(session) | Tells whether a session acts in its identity's own right (a signed-in person or an API key) rather than as a temporary credential. Plugins and custom routes use it to refuse self-service actions, such as accepting terms, from role sessions and session tokens, as the built-in APIs do. | |
const agentAttestationUri | The URI of the attestation extension IAM adds to capabilities.extensions of every card it signs. | |
amountDue(statement) | What is still owed on an invoice: its total less payments and credit notes (never below 0). | |
amountPaid(statement) | Payments received on an invoice; invoices marked paid before payments were recorded count as fully paid. | |
assertionKey(secret) | Derives, from the deployment secret, the shared key that signs and verifies assertions (iam.assertionKey() returns the current one). Services that receive assertions verify them with it, so keep it as secret as the secret itself. | Architecture overview |
auditEventHash(event) | The hash of an event: SHA-256 over the canonical JSON of every field except hash itself. Re-exported from @better-iam/core. | |
const authenticatedAuthMethods | The names of the auth methods the HTTP handler serves only to a signed-in caller, such as signOut and listSessions. | |
betterIam(options) | Creates your Better IAM instance from its options: the database, the deployment secret, the public URL, and the rest. The instance carries the typed server API (iam.api), the HTTP handler, and the authorization helpers. Create it once and import it wherever server code needs identity or access. | Deployment |
billingPeriod(value, name?) | A billing period YYYY-MM. | |
budgetWindow(period, now) | The current window of a period (UTC), as [start, end). | |
canonicalJson(value) | Deterministic JSON: object keys sorted recursively, undefined properties omitted, arrays kept in order. Re-exported from @better-iam/core. | Audit chain |
configOptions(config, context?) | The options a defineConfig value stands for: a factory is called with context (default: this process's environment and working directory), plain options are returned as they are. | |
createInferenceGateway(runtime, options?) | Builds the inference gateway, an HTTP handler that lets any Better IAM credential call AI models through the Anthropic Messages and OpenAI Chat Completions APIs without holding a provider key. | |
createJsonlAuditArchive(options) | A file sink for auditArchive: one JSON Lines file per batch at {directory}/{tenantId}/{fromSequence}-{toSequence}.jsonl (sequences zero-padded, so files sort in chain order). | Scheduled jobs |
createMetrics(options?) | Creates a standalone Prometheus-style metrics collector that you feed from your own onSpan hook. Most deployments use the one built from the metrics option instead; see observability. | Observability |
createSessionTokenVerifier(options) | Verifies session JWTs issued by Better IAM in your other services, offline, against the published keys (GET {basePath}/.well-known/jwks.json or iam.sessionTokens.jwks()). | Temporary access |
dayOf(at, timeZone) | The local day YYYY-MM-DD an instant falls on. | |
defineConfig(config) | Types a deployment configuration for better-iam.config.{mjs,ts}: options, or a factory of them that receives { command, env, cwd } from the CLI. It returns its argument unchanged; the value is autocompletion and checking. | |
defineTenantConfig(config) | Types a tenant's configuration as code (roles, policies, groups, bindings, packages, invariants, agreements) for better-iam config-plan|config-apply --input tenant.config.ts, or a factory that computes it per tenant and environment. | |
const delegationTokenLimits | Lifetimes (seconds) and the longest chain of actors a delegation token carries. Re-exported from @better-iam/core. | |
const delegationTokenType | The JWT typ header of delegation tokens: verifiers refuse any other. Re-exported from @better-iam/core. | |
departmentHeads(tx, tenantId, departmentId, options?) | The heads of a department (identity IDs): its own head and, with includeAncestors, the heads of the departments above it, nearest first and without duplicates. | |
departmentOf(tx, tenantId, identityId) | The ID of the department a person belongs to, if any. | |
departmentPath(tx, tenantId, departmentId) | Department IDs from the top of the tree down to departmentId itself (for roll-ups); empty when unknown. | |
class IamError | The same IamError class as @better-iam/core, re-exported so server code needs one import. Check error.code to handle a specific refusal. Re-exported from @better-iam/core. | Adapters and plugins |
const inferenceAction | The action that calling an AI model needs, inference:invoke, which the inference option adds to the catalog. Policies grant it on model/{name}; use the constant in checks and policies you build in code so they match what the inference gateway and inference.check decide. | |
const inferenceResourceType | The resource type of AI models, model, which the inference option adds to the catalog. A model published with inference.createModel is the resource model/{name}, with its tier, family, provider, and prices as attributes for conditions. | |
const inferenceToolAction | The action decided on each model-tool/{kind} a request asks for, for models whose providerTools is policy. | |
const inferenceToolResourceType | Tools the provider runs itself (web search, code execution, remote MCP servers, ...), as resources of this type named by kind (model-tool/web_search, model-tool/mcp:{host}), checked with inference:use-tool for models whose providerTools is policy. | |
isTeamMaintainer(tx, tenantId, teamId, identityId, options?) | Whether a person maintains a team: a live maintainer membership of the team itself or, with includeAncestors, of any team above it (a parent team's maintainers manage its child teams too). | |
lintPolicy(document, context?) | Lints a policy document: validates it as storage would, then reports statements that grant more than intended, conditions that can never match or silently fail open, and statements that are shadowed or duplicated. The context tells the linter which identity attributes, resource attributes, and application keys exist. | Policy documents |
looksLikeJwt(value) | Tells a session JWT apart from an opaque token by its shape (three dot-separated segments), so code that accepts both can route each to the right check. It proves nothing about validity. | |
machineIdentity(identity) | Machine accounts: service accounts and agents. They hold API keys and never sign in. | |
nextWatermark(current, before, now) | Computes the next "revoke sessions issued before" time for a role, trust, or OIDC provider: it only ever moves forward and never into the future. Custom revocation tools use it to match roles.revokeSessions. | |
periodBounds(period, timeZone) | The first instant of a period and of the next one. | |
periodOf(at, timeZone) | The billing period an instant falls in. | |
priceBreakdown(spec, quantity) | How a quantity is priced, tier by tier, for invoice sub-lines: the tiers used, the free units, and what the tiers came to before the price's minimum or maximum. | |
priceQuantity(spec, quantity) | The amount, in micros, a period's quantity costs under a price: its tiers, then its minimum and maximum. | |
priceSpec(value) | Validates a price given in currency units (unitAmount, tiers[].unitAmount / flatAmount, packageAmount) and returns it in micros. Tiers ascend by upTo, and the last one has upTo: null. | |
primaryTeamOf(tx, tenantId, identityId, at?) | The person's oldest live direct team membership, for callers that attribute to one team only. | |
providerToolsOf(path, body) | The tools a request asks the provider to run (or that the provider defines for the model to drive): Anthropic server and Anthropic-defined tools (tools[].type other than custom) and remote MCP servers (mcp_servers); OpenAI Responses built-in tools (tools[].type other than function and custom, MCP servers as mcp:{host} or mcp:{connector_id}), and a stored prompt (prompt, which may bring tools of its own); Chat Completions web search (web_search_options). | |
const publicApiMethods | The few API methods the HTTP handler serves without a credential, such as accepting an invitation (the emailed token is the proof) or looking up a tenant by its alias. | |
const publicAuthMethods | The names of the auth methods the HTTP handler serves without a session, such as signIn and resetPassword. Exported so tools and tests can see the route table the handler enforces. | |
publicOidcProvider(provider) | Turns a stored OIDC provider into the record the API returns, an explicit list of its public settings. Use it when you read providers straight from storage. | |
publicTrust(trust) | Turns a stored trust into the record the API returns: every setting a reviewer needs, with requiresExternalId in place of the stored external ID hash. Use it when you read trusts straight from storage, for example in a custom export, so the hash never leaves the server. | |
readDelegationTokenClaims(claims, expected) | Checks the claims of a (signature-verified) delegation token against what the verifier expects: well formed, from an accepted issuer, for exactly this audience (and tenant), current within the clock tolerance, and issued for at most delegationTokenLimits.maxSeconds. Re-exported from @better-iam/core. | |
renderInvoiceHtml(statement, options?) | The invoice as a standalone HTML page (print it or save it as PDF): issuer, bill-to, number and dates, lines with tier sub-lines and service periods, discounts, commitment, credit, tax, payments, credit notes, and amount due. | |
revokedByWatermark(createdAt, ...watermarks) | Tells whether a session created at a given time falls under any of the given "revoke sessions issued before" times, the check IAM applies to role sessions on every use. | |
rolloutBucket(key, tenantId) | The rollout position (0 to 99.99) of a tenant branch for a flag: stable per key and tenant, so raising the percentage only ever adds tenants, and different flags spread over different tenants. | Feature flags |
const routeGroups | The API groups the HTTP handler exposes under {basePath}/{group}/{method}. Groups not in this set are callable only from server code. | |
const SESSION_TOKEN_ALGORITHMS | The two signature algorithms session JWTs may use, EdDSA and ES256. Signing keys and verifiers accept nothing else. | |
const SESSION_TOKEN_TYPE | The typ header every Better IAM session JWT carries, biam-session+jwt, which keeps session tokens from being confused with assertions, OAuth access tokens, or tokens from other issuers. | |
class SessionTokenError | The error a session-token verifier throws for any token it rejects. reason says why, for logs and metrics; answer the caller with a plain 401. | |
shiftPeriod(period, months) | A period months after (or before, when negative) another. | |
teamMaintainers(tx, tenantId, teamId, at?) | The live direct maintainers of a team (identity IDs, oldest first). | |
teamsOf(tx, tenantId, identityId, options?) | The teams a person belongs to at at (default now): their live direct memberships (oldest first) and, with includeAncestors, the parent teams those memberships make them part of. Team IDs, never backing group IDs. | |
const temporarySessionKinds | The session kinds that are temporary credentials, role, session-token, and delegated (an AI agent acting for a person): derived from a source, bounded by it, and never allowed to pass recent-authentication or self-service checks. | |
usageCost(model, usage) | Cost of a call in micro-dollars: tokens × dollars per million tokens (cached input at its own price when set). | |
usageFrom(format, usage) | Token counts from a provider's usage object (Anthropic, OpenAI Chat Completions / Embeddings, or OpenAI Responses); undefined when there is none. Cached input tokens are counted apart from other input. | |
validateTenantConfig(value) | Validates the shape of a desired configuration; references are checked against the tenant during planning. | |
verifyAssertion(token, options) | Verifies an assertion against the derived key, audience, optional issuer, and time; returns its claims. key may list several keys (iam.assertionKeys()) while a deployment secret rotates. | Operations recipes |
verifyAuditChain(events, options?) | Verifies a run of events from one tenant: contiguous sequences, each previousHash equal to the previous event's hash (or previousHash of the first event when the run starts mid-chain), and every hash recomputable. Events are sorted by sequence first, so exports and database reads can be passed as they come. Re-exported from @better-iam/core. | Audit chain |
verifyWebhookSignature(input) | Verifies a webhook signature produced by Better IAM. signature is the X-Better-IAM-Signature header value. | Webhooks |
webTrustTagClaims(value) | Checks a web-identity trust's tagClaims mapping (session tag keys to token.{claim} names, at most 10) and returns it cleaned, the same way trust.create and trust.update do, so tools that prepare trusts ahead of time fail early. | |
class WrongRegionError | The organization is served by another region's deployment. location is its sign-in URL there (when one can be built), so a sign-in page can redirect instead of showing an error. Answered with HTTP 421 Misdirected Request. |
@better-iam/server/assertions
| Export | What it does | Explained in |
|---|---|---|
assertionKey(secret) | The verification key for a deployment secret: SHA-256 of a purpose-bound derivation, as hex. | Architecture overview |
createAssertionsApi(ctx) | Builds the iam.api.assertions group from the server's internal context. betterIam() calls it for you; applications use iam.api.assertions, and the other exports of this entry point verify assertions. | |
verifyAssertion(token, options) | Verifies an assertion against the derived key, audience, optional issuer, and time; returns its claims. key may list several keys (iam.assertionKeys()) while a deployment secret rotates. | Operations recipes |
@better-iam/server/session-tokens
| Export | What it does | Explained in |
|---|---|---|
createSessionTokenVerifier(options) | Verifies Better IAM session JWTs in downstream services without contacting IAM. This entry point imports nothing from Node, so it runs in edge middleware, workers, Bun, and Deno as well as Node; point jwks at the IAM JWKS route or pass the key set, and call verifyRequest(request) from any framework. | Temporary access |
looksLikeJwt(value) | True for a compact JWS shape (three base64url segments); says nothing about validity. | |
const MAX_SESSION_TOKEN_LENGTH | The longest session JWT Better IAM issues or accepts, 4096 characters, so services can refuse oversized headers before verifying them. | |
const SESSION_TOKEN_ALGORITHMS | The only signature algorithms IAM issues or accepts for session JWTs. | |
const SESSION_TOKEN_TYPE | The typ header of every IAM session JWT; other token classes (assertions, OAuth at+jwt) never carry it. | |
class SessionTokenError | Every verification failure. reason is for logs and metrics; clients should only see the 401. |
@better-iam/svelte
Svelte stores and SvelteKit hooks, guards, and actions.
| Export | What it does | Explained in |
|---|---|---|
createIam(options) | One typed client, one session store, and advisory authorization stores for a Svelte 4 or 5 app. Create it once (typically in the root +layout.svelte) and share it with setIamContext / getIamContext. | SvelteKit |
createSessionStore(client, options?) | Framework-agnostic session state. The React and Vue bindings subscribe to it; it can also drive other frameworks or plain scripts. Re-exported from @better-iam/client. | SvelteKit |
getIamContext() | The Iam a parent shared with setIamContext. | SvelteKit |
isUnauthenticated(error) | True when an error means the caller is not signed in any more or must confirm who they are (the server answered 401 or 403). Anything else is a network or server failure, worth a retry rather than a sign-in page. Re-exported from @better-iam/client. | SvelteKit |
setIamContext(iam) | Shares an Iam with descendant components; call during component initialisation. | SvelteKit |
@better-iam/svelte/kit
| Export | What it does | Explained in |
|---|---|---|
checkStepUp(session, requirement, now?) | Checks a session against a step-up requirement; null when it qualifies. Accepts the getSession result or its inner session record. Impersonated sessions always fail a recency requirement, as the server's own check does. Re-exported from @better-iam/middleware. | SvelteKit |
createIamKit(source, options?) | SvelteKit integration: handle serves the IAM HTTP API, enforces protect rules, and gives every request event.locals.iam; guard and action wrap server loads and form actions. | SvelteKit |
isAuthenticationError(error) | True for the errors getSession raises when there is no usable session. Re-exported from @better-iam/middleware. | SvelteKit |
isKitControlError(error) | True for SvelteKit's own control-flow throws (redirect(), error()), which must propagate untouched. | SvelteKit |
parseSetCookie(header) | Parses one Set-Cookie header into the name, decoded value, and options event.cookies.set accepts. | SvelteKit |
safeRedirectPath(value, fallback?) | A same-site relative path safe to redirect to, or fallback. Refuses schemes, //host, and backslash tricks. Re-exported from @better-iam/middleware. | SvelteKit |
@better-iam/vue
Vue plugin, composables, and the IamCan component.
| Export | What it does | Explained in |
|---|---|---|
createHydration(state?) | A plain object hydration store; serialize state into the page and pass the parsed object back on the client. | Vue |
createIam(options) | The Vue plugin: one typed client and one session store for the app. app.use(createIam({ client })). | Vue |
createSessionStore(client, options?) | Framework-agnostic session state. The React and Vue bindings subscribe to it; it can also drive other frameworks or plain scripts. Re-exported from @better-iam/client. | Vue |
const IamCan | Renders the default slot only when the advisory decision allows the action, the fallback slot otherwise, and the loading slot meanwhile. <IamCan tenant-id="t1" action="projects:delete" :resource="{ type: 'project', id }">. | Vue |
isUnauthenticated(error) | True when an error means the caller is not signed in any more or must confirm who they are (the server answered 401 or 403). Anything else is a network or server failure, worth a retry rather than a sign-in page. Re-exported from @better-iam/client. | Vue |
useAccessible(input) | The registered resources of a managed type the signed-in principal may act on; refetched when the input or identity changes. | Batches and reverse queries |
useAccessPaths(input) | Whether the signed-in person may perform an action and, if not, the self-service paths that would allow it. | Vue |
useAgreements(input) | The signed-in person's terms of use and a way to accept them; policies can hold back access until they do. | Vue |
useAuthorize(input) | Batched advisory decisions for rendering menus and buttons. Accepts a ref or getter so the checks can follow reactive state; the server still enforces every operation. | Batches and reverse queries |
useCan(input) | One advisory decision as a boolean ref, false while loading or signed out. | Batches and reverse queries |
useIamClient() | The client passed to createIam, typed as the caller declares it. | Nuxt |
useSession() | Reactive session state plus refresh, sign-out, and manual replacement. | Vue |
useTeams(input) | The signed-in person's teams with self-service joining and leaving (teams.listMine, requestToJoin, leave). |
Was this page helpful?
Last updated on