BetterIAM

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.

ExportWhat it doesExplained in
const A2A_ACCESS_DENIEDJSON-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_REQUESTEDJSON-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 agentAttestationUriThe URI of the attestation extension Better IAM adds to every card it signs.AI agents
class AgentCardErrorWhy 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 DelegationTokenErrorWhy 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 handoffMetadataKeyThe 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.

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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).

ExportWhat it doesExplained 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.

ExportWhat it doesExplained in
class AuthServiceThe 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 credentialTokenKindsMaps 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 credentialTokenScanPatternA 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

ExportWhat it doesExplained 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.

ExportWhat it doesExplained in
const builtinCommandsEvery built-in command, in help order.
class CliErrorA 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 configFileNamesConfiguration 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.

ExportWhat it doesExplained in
class ClientErrorAnother 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 IamClientErrorThe 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

ExportWhat it doesExplained 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 WebAuthnAbortServiceA service singleton to help ensure that only a single WebAuthn ceremony is active at a time.Typed client

@better-iam/client/session

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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 auditGenesisThe previousHash of the first event of every chain.
const authMethodsThe 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_SQLDistinct 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 delegationTokenLimitsLifetimes (seconds) and the longest chain of actors a delegation token carries.
const delegationTokenScopePatternOne scope a delegation token may carry: an action, or an action pattern whose only wildcard is *.
const delegationTokenTypeThe 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_FIELDSNumeric 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 IamErrorThe 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_FIELDSHigh-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_KEYReserved 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_STEPSThe 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_CONDITIONSMost typed conditions planQuery hands to a driver; further keys are filtered in memory.Adapters and plugins
const ORDERED_FIELDSNumeric 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_FIELDField 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 RecordStoreThe 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_FORMATPortable 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_VERSIONThe 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

ExportWhat it doesExplained in
adapterConformanceCases()A fresh copy of every conformance case, in a stable order.Adapters and plugins
class ConformanceFailureThe 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.

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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 IamRequestErrorA 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

ExportWhat it doesExplained 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

ExportWhat it doesExplained 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

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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_OPTIONSInjection token for the resolved IamAssertionOptions.NestJS
const IAM_INSTANCEInjection token for the betterIam() instance.NestJS
const IAM_OPTIONSInjection token for the resolved IamModuleOptions.NestJS
class IamAssertionGuardFor 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 IamAssertionModuleConfigures IamAssertionGuard for a service that trusts assertions from a Better IAM deployment.NestJS
class IamEventsExplorerSubscribes every @OnIamEvent provider method to the IAM event stream at bootstrap and, when dispatchIntervalMs is set, drives iam.events.dispatch() until shutdown.NestJS
class IamExceptionFilterRenders 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 IamFilterInterceptorThe 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 IamGuardAuthenticates 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 IamHttpMiddlewareNest middleware form of createIamRequestHandler, registered by IamModule.forRoot({ mount: true }).NestJS
class IamModuleBetter 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 IamServiceRequest-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

ExportWhat it doesExplained 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.

ExportWhat it doesExplained in
class AssertionErrorRaised by the edge verifiers; code and status match the server's IamError for the same failure.Next.js
const authFieldsForm 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 authStepFieldsHidden 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 pathnameHeaderThe 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

ExportWhat it doesExplained 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

ExportWhat it doesExplained in
class AssertionErrorRaised 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 pathnameHeaderThe 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.

ExportWhat it doesExplained in
export defaultThe 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

ExportWhat it doesExplained 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 IamH3ErrorAn 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.

ExportWhat it doesExplained 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 sharedSignalEventsSecurity event types the transmitter emits (CAEP and RISC).Shared Signals

@better-iam/projects

Reference tenant-scoped Projects plugin.

ExportWhat it doesExplained in
createProjectsPlugin()Reference plugin providing tenant-scoped project records.Adapters and plugins

@better-iam/react

React provider, hooks, and permission-gated components.

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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 agentAttestationUriThe 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 authenticatedAuthMethodsThe 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 delegationTokenLimitsLifetimes (seconds) and the longest chain of actors a delegation token carries. Re-exported from @better-iam/core.
const delegationTokenTypeThe 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 IamErrorThe 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 inferenceActionThe 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 inferenceResourceTypeThe 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 inferenceToolActionThe action decided on each model-tool/{kind} a request asks for, for models whose providerTools is policy.
const inferenceToolResourceTypeTools 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 publicApiMethodsThe 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 publicAuthMethodsThe 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 routeGroupsThe API groups the HTTP handler exposes under {basePath}/{group}/{method}. Groups not in this set are callable only from server code.
const SESSION_TOKEN_ALGORITHMSThe two signature algorithms session JWTs may use, EdDSA and ES256. Signing keys and verifiers accept nothing else.
const SESSION_TOKEN_TYPEThe 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 SessionTokenErrorThe 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 temporarySessionKindsThe 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 WrongRegionErrorThe 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

ExportWhat it doesExplained 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

ExportWhat it doesExplained 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_LENGTHThe longest session JWT Better IAM issues or accepts, 4096 characters, so services can refuse oversized headers before verifying them.
const SESSION_TOKEN_ALGORITHMSThe only signature algorithms IAM issues or accepts for session JWTs.
const SESSION_TOKEN_TYPEThe typ header of every IAM session JWT; other token classes (assertions, OAuth at+jwt) never carry it.
class SessionTokenErrorEvery 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.

ExportWhat it doesExplained 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

ExportWhat it doesExplained 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.

ExportWhat it doesExplained 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 IamCanRenders 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

On this page