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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
const agentAttestationUri | The URI of the attestation extension Better IAM adds to every card it signs. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
createA2aAuthorizer(options) | Decisions shared by the gate and by handlers written with an A2A SDK. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
memoryTaskOwners(options?) | In-memory owners: at most maxTasks entries (default 100000), each kept ttlMs (default seven days). | Agent-to-agent (A2A) |
taskOwnerOf(caller) | The owner key of a caller: the same person through the same agent (or none), or the same OAuth client and subject. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
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. | Agent-to-agent (A2A) |
withHandoff(message, delegationId) | Adds a hand-off to an A2A message's metadata (the calling side). | Agent-to-agent (A2A) |
@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(). | libSQL and Turso |
@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. | PostgreSQL |
@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. | SQLite |
@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. | |
checkFetchUrl(value, options) | Checks the URL rules: https on port 443 (any port with anyPort) without credentials or a fragment (loopback hosts may use http and any port with allowInsecureLocalhost), and, for an IP-literal host, a public address. Throws SafeFetchError ('url' or 'address') and returns the parsed URL. | |
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. | |
createGuardedFetch(options?) | A fetch under the SSRF rules: the URL rules of checkFetchUrl, and a connect-time DNS check that refuses hosts resolving to non-public addresses. Redirects are never followed: with redirect: 'error' a 3xx rejects as fetch would, otherwise it is returned as is. | |
createMemoryRateLimiter(options?) | In-process limiter for single-instance deployments and tests. Counters are not shared between processes, and the map is bounded by maxKeys. | HTTP and configuration |
createStoreRateLimiter(store) | The default limiter: durable counters in the IAM database, committed independently so rejected credentials cannot roll back their attempt. | Rate limits and lockouts |
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. | Tokens and JWTs |
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. | Tokens and JWTs |
decryptSecret(value, secret, context?) | Opens a sealed value with the current secret or, during a rotation, a previous one. | |
describeUserAgent(userAgent) | A short description of a User-Agent for security notices ("Chrome on Windows"). The header is chosen by whoever sent the request, so it never reaches a message verbatim: otherwise anyone could put their own text and links into a genuine sign-in notice by failing a sign-in with a crafted header. | Email and SMS |
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. | |
fetchJsonSafely(value, options) | GETs a JSON document under the SSRF rules above. Any status other than 200 fails ('redirect' for 3xx, else 'status'), as do a content type without "json", a body over maxBytes, the deadline, and unparseable JSON. | |
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. | |
isPublicAddress(address) | True for a globally routable unicast address; false for private, reserved and malformed values. | |
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. | Tokens and JWTs |
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. | API keys and service accounts |
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. | Tokens and JWTs |
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. | Email and password |
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, privacy-request-verify, privacy-request-received, privacy-request-update, privacy-request-due, workflow-message, threat-alert, license-waiting, license-activated, guest-invitation, guest-review, guest-sponsor-missing, clearance-reminder, clearance-status, owner-invitation, member-invitation) into a subject, plain text, and HTML, so a delivery callback can hand them to any provider. | Guests |
class SafeFetchError | A refused or failed guarded fetch; reason says which rule stopped it. |
@better-iam/auth/templates
| Export | What it does | Explained in |
|---|---|---|
describeUserAgent(userAgent) | A short description of a User-Agent for security notices ("Chrome on Windows"). The header is chosen by whoever sent the request, so it never reaches a message verbatim: otherwise anyone could put their own text and links into a genuine sign-in notice by failing a sign-in with a crafted header. | Email and SMS |
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, privacy-request-verify, privacy-request-received, privacy-request-update, privacy-request-due, workflow-message, threat-alert, license-waiting, license-activated, guest-invitation, guest-review, guest-sponsor-missing, clearance-reminder, clearance-status, owner-invitation, member-invitation) into a subject, plain text, and HTML, so a delivery callback can hand them to any provider. | Guests |
@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. | CLI |
cliManifest() | The machine-readable description of every built-in command (what better-iam help --json prints), for docs and tools. | CLI |
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 up to the repository root or home directory. | |
configFromEnv(env?) | Deployment options from environment variables alone (twelve-factor style), for containers and CI jobs that have no configuration file: | Databases |
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. | CLI |
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. | CLI |
findConfigFile(cwd) | The nearest configuration file in cwd or one of its parents, like Prettier and ESLint find theirs, without leaving the repository: the search stops at the repository root (a directory holding .git) or the home directory, and skips files another user could have planted (see trustworthy). | |
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. | Migrations |
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. | Build a multi-tenant B2B SaaS |
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. | CLI |
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. | CLI |
@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. | AI agents |
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. | Error handling |
@better-iam/client/device
| Export | What it does | Explained in |
|---|---|---|
createDeviceProver(options?) | Lets a browser or Node agent prove which registered device a request comes from, so policies can require a registered, managed, or compliant device. | Device posture |
const deviceProofHeader | The request header that carries a device proof. | Device posture |
indexedDbKeyStore(name?) | Keeps a browser's device key in IndexedDB between page loads, with a private key that page scripts can sign with but never read. It is the default key store in browsers. | Device posture |
memoryKeyStore() | Keeps the key pair in memory only: for tests, scripts, and servers that re-enrol after a restart. | Device posture |
@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 |
|---|---|---|
andFilter(filters) | Conjunction, simplified: nested ands flattened, true dropped, false absorbing, duplicates removed. | |
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 classificationIdPattern | Level and compartment ids: an ASCII letter or digit, then letters, digits, ., _, : or - (64 at most). | |
const classificationLimits | The bounds validateScheme and validateLabel enforce. | |
const classificationTemplates | Starting points for clearances.defineScheme({ template }), frozen (copy with validateScheme before changing). | Security clearances |
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 operations |
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. | Testing policies |
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. | |
describeFilter(filter) | A readable rendering of a filter, for logs, UIs and tests. | Data filtering |
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 |
dominates(party, label, scheme) | Whether a party may read a resource carrying label (no read up). | Security clearances |
encodeJsonbDocument(data) | Record JSON as the PostgreSQL adapter stores it: valid jsonb, reversible by decodeJsonbDocument. | PostgreSQL |
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. | Testing policies |
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). | Schema |
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 operations |
const falseFilter | The filter no resource passes. | |
filterMatches(filter, record) | Whether a resource passes a filter: record.id is the id and every other field is read by name (record['tag.team'] for resource.tag.team). This is exact, with the policy engine's semantics, and supports every filter. | Data filtering |
filterToMongo(filter, options?) | The filter as a MongoDB query document. Dates and IP addresses refuse with UNSUPPORTED_FILTER. | Data filtering |
filterToPrisma(filter, options?) | The filter as a Prisma where object. Globs must be exact, a prefix (abc*), a suffix (*abc) or a substring (*abc*); dates, IP addresses, and other globs refuse with UNSUPPORTED_FILTER. Case-insensitive comparisons use mode: 'insensitive' (PostgreSQL and MongoDB). | Data filtering |
filterToSql(filter, options) | The filter as a parameterized SQL expression. Columns are expected to hold values of the types the policy compares (text for string conditions, numbers, booleans, ISO 8601 text for dates), with NULL for absent attributes. PostgreSQL uses $n placeholders and SQLite ?. | Row-level data filtering |
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. | Write a database adapter |
fixedPlan(allowed) | A plan that allows everything or nothing (root override, a fixed refusal). | |
globMatches(tokens, value) | Glob matching over code points, greedy with backtracking to the last star (as the engine does). | |
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. | Error handling |
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 operations |
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. | Schema |
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. | Optimize performance |
intersectPlans(left, right) | Both plans at once: what each allows (an impersonation session and the administrator behind it). | |
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"). | |
isValidClassificationLabel(label, scheme) | True when label is a valid label of the scheme; the non-throwing form of validateLabel. | |
joinLabels(a, b, scheme) | The least restrictive label at least as restrictive as both: the higher level, the union of compartments, NOFORN when either has it, and the intersection of releasableTo lists (an absent list is unrestricted, so the other list stands; disjoint lists leave an empty list, owner countries only). | Security clearances |
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. | |
labelCovers(upper, lower, scheme) | True when replacing lower with upper never declassifies: both are valid labels of the scheme, upper is at least as high, carries every compartment of lower, keeps NOFORN when lower has it, and is releasable to no country lower is not (owner countries always count). Anything else needs a declassification. | Security clearances |
labelRank(label, scheme) | The rank of the label's level in the scheme; undefined when the level is unknown (callers fail closed). | |
legacyRiscSubject(value) | Reads the subject of a legacy RISC event (Google's RISC, and SSF drafts before RFC 9493): events[type].subject with a hyphenated subject_type instead of format. | |
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. | Schema |
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 |
notFilter(filter) | Negation, simplified: constants flip and a double negation cancels. | |
const ORDERED_FIELDS | Numeric fields SQL adapters index for findOrdered within a tenant (audit time and sequence). | Schema |
orFilter(filters) | Disjunction, simplified: nested ors flattened, false dropped, true absorbing, duplicates removed, and equals on the same field (and case rule) merged into one value list. | |
parseGlob(pattern) | A filter glob back into tokens (the inverse of globString). | |
parseSubjectIdentifier(value) | Reads an RFC 9493 subject identifier (or an SSF complex one) strictly: known formats only, every string 1 to 512 characters without control characters, email, acct:, DID and URI values well formed, at most 10 aliases and no alias list inside another, no complex subject inside another, and at most three levels of nesting. | |
planQuery(collection, filter, capabilities?) | Splits a validated filter into driver conditions and keys left to the in-memory filter. | Adapters and plugins |
planResources(input) | Plans the resources of resourceType the principal may perform action on. The result mirrors the decision the server makes for each resource: no deny statement applies (across every grant path and ceiling), every ceiling lets the resource through, and some grant path allows it within its own ceilings. | Optimize performance |
const planWorkLimit | The most work one plan may take (pattern states visited and filter atoms built), so that policies full of wildcards cannot make planning slow or its filter huge. A plan that needs more refuses with UNSUPPORTED_FILTER. | Data filtering |
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. | |
readSecurityEvent(payload) | Reads the claims of a Security Event Token after its signature, issuer, audience and typ were verified (and before it is acted on). | |
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. | Write a database adapter |
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. | Migrations |
signalEventType(uri) | The event type an event-type URI names (exact match), or unknown. | |
const signalEventUris | The event-type URI of each known security event, as SSF 1.0, CAEP 1.0 and RISC 1.0 name them. | |
class SignalFormatError | Why a SET's claims were refused: the receiver answers the transmitter with invalid_request for each. | |
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. | Storage operations |
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. | Write a database adapter |
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. | |
const trueFilter | The filter every resource passes. | |
userSubjects(subject) | The identifiers in a subject that may name a person, without repeats: the subject itself when it is an iss_sub, email, opaque, account or phone_number identifier, the user member of a complex subject, and each entry of an alias list (expanded the same way). | |
validateLabel(label, scheme) | Validates a label against a scheme and returns it normalized: compartments and countries sorted, an empty compartment list and noforn: false dropped, an empty releasableTo kept (it means owner countries only). | Security clearances |
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. | |
validateScheme(input) | Validates a scheme definition and returns a fresh copy (absent compartments, ownerCountries and caveats read as empty). Throws IamError INVALID_INPUT. Messages name positions, never compartment names or submitted values. | Security clearances |
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. | Write a database adapter |
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. | Write a database adapter |
@better-iam/ldap
A read-only LDAPv3 directory gateway over Better IAM: people, groups and password binds for applications that only speak LDAP.
| Export | What it does | Explained in |
|---|---|---|
class BerError | The subset of ASN.1 BER (X.690) that LDAPv3 (RFC 4511) uses: definite lengths, INTEGER/ENUMERATED, BOOLEAN, OCTET STRING, NULL, SEQUENCE/SET and context/application tags. Decoding is strict (no indefinite lengths, lengths at most four bytes) and bounds-checked; anything malformed throws BerError. | LDAP gateway |
buildEntries(data) | The tree under the tenant's base DN: the base entry, ou=people (inetOrgPerson entries named uid={uid}), ou=groups (groupOfNames named cn={name}, with member DNs) and ou=services (service accounts and agents, named cn={name}). | LDAP gateway |
createLdapServer(options) | A read-only LDAPv3 gateway over Better IAM. | LDAP gateway |
decodeFilter(item, depth?, budget?) | Decodes a BER filter. Deep or huge filters are refused (a search is evaluated against every entry). | LDAP gateway |
decodeMessage(message) | Decodes one LDAPMessage element. | LDAP gateway |
decodeResponse(message) | Decodes one server answer read with readElement: a search entry (dn and attributes) or a result (code, message, and an extended response's responseName and responseValue), with its controls. The client-side counterpart of the encode* helpers. | LDAP gateway |
depthBelow(dn, base) | How many RDNs dn has below base (-1 when it is not under it). | LDAP gateway |
class DnError | Distinguished names (RFC 4514): parsing with escapes (\,, \2C), quoting of values, and a normalized form for comparisons (attribute types and values lowercased, insignificant spaces trimmed). Multi-valued RDNs (+) are kept in order. | LDAP gateway |
encodeBind(id, name, password) | Encodes an LDAPv3 simple bind request (message ID, bind DN, password) as BER. With the other encode* helpers it lets tests and tools talk to the gateway, or any LDAP server, without an LDAP client library. | LDAP gateway |
encodeCompare(id, entry, attribute, value) | Encodes a compare request: does the entry with this DN hold this value of this attribute? The server answers with result code compareTrue or compareFalse. | LDAP gateway |
encodeExtended(id, name, value?) | Encodes an extended request by its OID with an optional value, for example encodeExtended(2, OID.whoAmI) to ask the gateway which account the connection is bound as. | LDAP gateway |
encodeFilter(filter) | Encodes a search filter object as the BER a search request carries, the inverse of decodeFilter. parseFilter turns an RFC 4515 string such as (&(objectClass=person)(mail=*)) into the object. | LDAP gateway |
encodeSearch(id, search, controls?) | Encodes a search request: base DN, scope (sub by default), filter, requested attributes, size limit, and types-only, with optional request controls such as those from pagedResultsRequest. | LDAP gateway |
encodeUnbind(id) | Encodes the unbind request that ends an LDAP session. | LDAP gateway |
escapeDnValue(value) | Escapes an attribute value for use in a DN. | LDAP gateway |
formatDn(rdns) | Formats RDNs as a DN string. | LDAP gateway |
isUnder(dn, base) | Whether dn equals base or lies below it. Compared RDN by RDN, never as strings: cn=a\,ou=people,dc=x is not under ou=people,dc=x. | LDAP gateway |
matchFilter(filter, attributes) | Evaluates a filter (RFC 4511 three-valued logic collapsed: Undefined counts as false). | LDAP gateway |
normalizeDn(dn) | The comparison form of a DN: lowercased, re-escaped, spaces normalized. Throws on malformed DNs. | LDAP gateway |
const OID | The object identifiers of the LDAP extensions the gateway's messages use: the "Who am I?" extended operation (the one it supports), StartTLS (which it does not offer; serve LDAPS with tls instead), the notice of disconnection it sends before closing a connection, and the paged-results control. | LDAP gateway |
pagedResultsRequest(size, cookie?) | Builds the request controls of a paged search (RFC 2696): the page size and the cookie from the previous page's response, empty for the first page. Pass the result to encodeSearch. | LDAP gateway |
parentDn(dn) | The normalized parent of a normalized DN ('' for a single RDN). | LDAP gateway |
parseDn(dn) | Parses a DN into RDNs (each a list of type/value pairs; most have one). The empty DN is the root. | LDAP gateway |
parseFilter(text) | Parses the RFC 4515 string form, e.g. (&(objectClass=person)(|(uid=alice)(mail=*@acme.test))). | LDAP gateway |
readElement(buffer, offset?, maxSize?) | Reads one element at offset, or undefined when buffer does not yet hold all of it (stream framing). maxSize bounds the content length a peer may announce. | LDAP gateway |
const ResultCode | LDAPv3 messages (RFC 4511) as the gateway reads and writes them. | LDAP gateway |
selectAttributes(target, requested) | The attributes a search returns for an entry: all user attributes for none or *, operational ones for + or by name, only the named ones otherwise, nothing for 1.1. | LDAP gateway |
@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. | MCP servers |
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. | MCP servers |
protectedResourceMetadataUrl(resource) | Where RFC 9728 metadata lives for a resource: /.well-known/oauth-protected-resource + the resource path. | MCP servers |
@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. | Node.js and custom servers |
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. | Node.js and custom servers |
createRequestHelpers(resolveIam, binding, options?) | Builds the per-request helpers over a framework's request and response. Framework adapters call this once per request. | Node.js and custom servers |
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. | Node.js and custom servers |
errorBody(error) | The IAM API's JSON error envelope, used by every adapter for refusals. | Node.js and custom servers |
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. | Node.js and custom servers |
errorStatus(error) | Reads the HTTP status of an error without assuming it is an IamError; undefined for anything else. | Node.js and custom servers |
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. | Hono |
isAuthenticationError(error) | True for the errors getSession raises when there is no usable session. | Node.js and custom servers |
isIamRefusal(error) | True for any error carrying an IAM code and an HTTP status (server IamError, client errors, IamRequestError). | Node.js and custom servers |
nodeHeaders(record) | Converts a Node IncomingMessage-style header record into Headers. | Node.js and custom servers |
parseCookieHeader(header) | Splits a Cookie header into name/value pairs (values left encoded). | Node.js and custom servers |
refusalResponse(error, request, pages) | How a guard should answer a refusal: a redirect for page navigations when a page is configured, else JSON. | Node.js and custom servers |
safeRedirectPath(value, fallback?) | A same-site relative path safe to redirect to, or fallback. Refuses schemes, //host, and backslash tricks. | Hono |
setCookieSummary(header, now?) | The name, raw value, and whether a Set-Cookie header deletes the cookie (Max-Age=0 or a past Expires). | Node.js and custom servers |
tenantOf(session) | The tenant a session acts in. | Hono |
underPath(pathname, prefix) | True when pathname is prefix or below it on a segment boundary. | Node.js and custom servers |
withQuery(target, params) | Appends query parameters, skipping undefined values. | Hono |
@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 |
@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. | 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. | Hono |
@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. | NestJS |
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. | Advanced |
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. | Advanced |
isNextControlError(error) | True for Next's control-flow throws (redirect, notFound, forbidden, unauthorized), which must propagate. | Advanced |
matchPath(pattern, pathname) | Glob over URL paths: * matches within one segment, ** across segments. | Middleware |
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. | Middleware |
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. | Advanced |
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. | Integrations |
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. | Build a multi-tenant B2B SaaS |
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. | Server actions and forms |
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. | Integrations |
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. | Advanced |
useSession() | The current session snapshot plus refresh, sign-out, and manual replacement (after a sign-in response). Re-exported from @better-iam/react. | Migrate from Auth.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. | Advanced |
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. | Middleware |
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. | Middleware |
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. | Advanced |
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 (at most 2 MiB, else it throws), 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(...). | Migrate from Auth0 |
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. | MCP servers |
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 |
useMyApps(options) | The signed-in person's app launcher (applications.mine): apps they can open now, most recently used first, and requestable apps they may ask for through an access package. launch records the launch and returns the app's sign-in URL; open it yourself (a new tab keeps the launcher). | Application catalog |
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 |
usePrivacy(options) | The signed-in person's privacy choices (privacy.mine): every purpose with their decision and its effect, their data-subject requests, and the privacy contact. | Privacy and consent |
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). | Teams and departments |
@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. | React Router |
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. | React Router |
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. | Agent-to-agent (A2A) |
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. | Server API |
assuranceOf(result, registered) | The assurance a request gets from a device: none unless registered (a verified, active device). | |
attachLabel(ctx, tx, tenantId, resource, known?) | Attaches a resource's effective classification label as the server-owned classification field (never an attribute): its IAM label, joined with the labels inherited from managed parents (at most 16 levels) and with the classification the application's resolver returned, which can therefore only raise it. | |
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. | Upgrade to 0.3 |
billingPeriod(value, name?) | A billing period YYYY-MM. | |
budgetWindow(period, now) | The current window of a period (UTC), as [start, end). | |
buildSshKrl(input) | A binary OpenSSH key revocation list (PROTOCOL.krl) for sshd RevokedKeys and ssh RevokedHostKeys: certificate serials and key IDs per authority, plus plain keys revoked outright (such as a disabled host's key). | |
canonicalJson(value) | Deterministic JSON: object keys sorted recursively, undefined properties omitted, arrays kept in order. Re-exported from @better-iam/core. | Audit chain |
const clearanceCollections | The collections of the clearance module (tenant scoped; tenant purge sweeps them). | |
const clearanceLimits | Limits of the clearance module. | |
clearanceScope(ctx, tx, principal, target, chain, agentScope, now, root?) | The mandatory part of a decision for one session in target: undefined when there is no scheme to enforce there (enforcedScheme: none in force and no label left over from one) or the principal is a root administrator and clearances.appliesToRoot is false. | |
const complianceChecks | The compliance center's built-in checks, each with its id, title, description and params (name, default and range), as compliance.catalog returns them (compliance guide). | Audit readiness for SOC 2 |
const complianceFrameworks | The built-in framework mappings (SOC 2, ISO 27001, NIST 800-53 and GDPR): each requirement with the checks that are evidence for it, not full coverage of it (compliance guide). | Audit readiness for SOC 2 |
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. | TypeScript |
consentState(purpose, consent, restricted, now) | The processing decision for one purpose and subject. Restriction holds back everything except legal obligations and vital interests; bases other than consent and legitimate interests are allowed without a record. | |
createCertificateRequest(input) | Builds a PEM PKCS#10 certification request for privateKey with a subject and subject alternative names, signed with the key (proof of possession). Clients call it to request certificates without OpenSSL. | Private CA |
createDisclosure(name, value) | Creates one SD-JWT disclosure: the salted [salt, name, value] array as base64url JSON, with the SHA-256 digest the issuer signs in the claim's place. The issuer uses it for every selectively disclosable claim; export it for tests and hand-built SD-JWTs. | |
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). | Audit chain |
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()). | Tokens and JWTs |
const credentialTypeResource | The resource type of verifiable credential types, credential-type. Policies allow vc:request on credential-type/{name} to let people get a credential of that type for themselves (who gets credentials). | |
dayOf(at, timeZone) | The local day YYYY-MM-DD an instant falls on. | |
const DEFAULT_SIGNAL_ALGORITHMS | Used when a source does not name its algorithms. | |
defaultGuestSettings() | The settings a tenant has without stored ones. | |
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. | TypeScript |
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. | TypeScript |
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. | Teams and departments |
departmentPath(tx, tenantId, departmentId) | Department IDs from the top of the tree down to departmentId itself (for roll-ups); empty when unknown. | Teams and departments |
const deviceProofHeader | The request header that carries a device proof (a compact JWS). | Device posture |
effectiveRisk(record, now, halfLifeHours) | The score and level in force at now: decayed contributions, raised to an unexpired override's level. | |
effectiveScheme(tx, chain) | The scheme in force for a tenant, given its ancestry ([tenant, parent, ..., root]): the one defined closest to the root. Undefined when no tenant of the chain defines one. | |
evaluateCompliance(device, integration, settings, now) | Judges a device against the tenant's requirements. | |
generateSecretValue(generator) | A random value from the generator: uniform draws, with one character of each kept class placed at random. | |
generateSshAuthorityKey() | A new Ed25519 authority key, with the private key as base64 PKCS#8 DER (the caller seals it). | |
const guestCollections | The collections this module owns, all tenant-scoped (lifecycle.ts purges them with their tenant). | |
const guestLimits | Guest lifetimes and list sizes: defaults and bounds, in days where they are durations. | |
const HOLDER_PROOF_TYPE | The typ of the wallet's proof of possession in OpenID4VCI (openid4vci-proof+jwt), sent with a credential request so the credential is bound to the wallet's key. | |
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. | Error handling |
inboundRefusal(settings, origin) | Why the host's inbound settings refuse a guest from origin, or undefined when they admit them. A refusal wins (a partner entry with allow: false, a blocked domain); a partner entry with allow: true then admits the guest over the defaults (allowGuests, allowedDomains). | |
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. | |
issueSdJwt(input) | Issues an SD-JWT: plain claims are visible to anyone holding the credential; each disclosable claim becomes a disclosure the holder decides to reveal or keep. Random decoy digests hide how many claims exist. Returns the issued form <jwt>~<disclosure>~...~ and its parts. | |
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). | Teams and departments |
const KB_JWT_TYPE | The typ of the key-binding JWT (kb+jwt) a holder appends to an SD-JWT presentation to prove it holds the credential's key, for the verifier's audience and nonce. | |
labelKey(type, resourceId) | The natural key of a resource's label: {type}/{id}, hashed when it would exceed 512 UTF-8 bytes. | |
labelsForType(tx, tenantId, type) | The effective IAM-held labels of every labeled resource of one type in a tenant, by resource id, for listings: own labels joined with what registered resources inherit from their managed parents. Labels an application resolver asserts are not included (decisions still apply them). | |
licenseCapacity(pools, now) | The seats a set of pools provides at now. | |
const licenseCollections | The storage collections of license management: licenseProducts, licensePools, licenseAssignments, licenseSeats, and licenseSettings, all tenant-scoped and purged with their tenant. | |
const licenseContextKey | The policy key listing the product keys a person holds an active seat for in the decision's tenant. | |
licenseKey(value) | Validates a product key: lowercase letters, digits, dots, underscores or hyphens, starting with a letter or digit. | |
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. | Testing policies |
liveLicensePool(pool, now) | Whether a pool contributes capacity at now. | |
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. | |
const maxLicenseAssignmentsPerProduct | Direct and group assignments of one product in one tenant. | |
const maxLicenseFeatureKeys | Feature keys one product may list. | |
const maxLicensePoolQuantity | Seats one pool may carry. | |
const maxLicensePoolsPerProduct | Pools (live or ended) one tenant may hold for one product; ended pools are swept 400 days after their end. | |
const maxLicenseProductsPerTenant | Products one tenant may define. | |
const maxSignalSourcesPerTenant | Signal sources one tenant may register. | |
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. | |
normalizeBaseDn(value) | Validates a base DN and returns its comparison form: attr=value components of letters, digits, spaces, ., _ and - (no escapes), lowercased with spaces collapsed, exactly as @better-iam/ldap normalizes DNs. | |
outboundAllows(settings, hostTenantId) | Whether a home tenant's outbound settings let its people become guests of hostTenantId. | |
parseSshCertificate(line) | Decodes a certificate line (*-cert-v01@openssh.com base64 [comment]). Only Ed25519 authorities verify. | |
parseSshPublicKey(line, options?) | Parses and validates one public key line (type base64 [comment]). Certificates, DSA keys, RSA keys under 2048 bits, malformed points and trailing data are refused. | |
periodBounds(period, timeZone) | The first instant of a period and of the next one. | |
periodOf(at, timeZone) | The billing period an instant falls in. | |
presentSdJwt(credential, options) | The holder's presentation: the credential with only the named claims disclosed, and a key-binding JWT signed with the holder key over aud, nonce, iat and the hash of everything before it. | Verifiable credentials |
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. | Teams and departments |
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). | Model access and budgets |
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. | Server API |
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. | Server API |
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. | |
class QuotaExceededError | The error enforce throws: 429 with the time to retry (Retry-After over HTTP). | API quotas |
quotaWindow(period, at, zone) | The window of a period that contains at: minutes and hours in UTC, days, ISO weeks and months in zone. | |
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. | |
readDisclosure(encoded) | Decodes a disclosure without trusting it (for wallets choosing what to reveal). | |
readStatusList(token, key, options) | Verifies a Status List Token for uri and returns its raw list. | Verifiable credentials |
const regulationDeadlines | The statutory response windows data-subject requests are answered within, per regulation: responseDays and the one extension allowed (extensionDays). GDPR and UK GDPR give 30 days plus 60, CCPA 45 plus 45, LGPD 15 with no extension, PIPEDA and other 30 plus 30. | |
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. | |
resolveDeviceSettings(stored) | The requirements for a tenant: the stored settings over the defaults (stored values were validated on write). | |
resolveThreatSettings(stored?) | Applies rule defaults and deployment defaults to a tenant's stored settings (absent when never configured). | |
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. | |
riskLevelFor(score) | Maps an identity risk score (0 to 100) to its level: high from 70, medium from 40, low from 10, and none below (riskThresholds). Policies read the level as principal.riskLevel (identity risk). | |
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 SD_JWT_VC_TYPE | The typ of an SD-JWT VC (vc+sd-jwt, the earlier name, is accepted when verifying). | |
class SdJwtError | A presentation or credential that did not verify, with the reason. | Verifiable credentials |
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. | Tokens and JWTs |
setStatusAt(bytes, index, bits, value) | Writes the status of index into a raw list. | |
shiftPeriod(period, months) | A period months after (or before, when negative) another. | |
const signalCollections | Where the receiver keeps its records; both are tenant-scoped and purged with the tenant (lifecycle.ts). | |
class SignalRejectedError | A refused security event token. err is the RFC 8935 error code, the message its description. temporary marks a refusal that may pass later (the source's keys could not be fetched): pushes answer 503 and polls leave the event unacknowledged, so the transmitter delivers it again. | Error handling |
signSshCertificate(authority, spec, comment?) | Issues an OpenSSH certificate; returns the certificate blob and its *-cert.pub line. | |
signStatusList(input) | A Status List Token (JWT, typ: statuslist+jwt) for a raw list. | |
splitSdJwt(value) | Splits <jwt>~<d1>~...~<dn>~[<kb-jwt>]. | |
const SSH_CERT_HOST | The OpenSSH certificate type of a host certificate (2); user certificates have SSH_CERT_USER (1). | |
const SSH_CERT_USER | Certificate kinds (PROTOCOL.certkeys type). | |
sshFingerprint(blob) | SHA256: plus the unpadded base64 SHA-256 of a key blob. | |
const sshForwardingActions | Forwarding a certificate allows only when every host it names allows it (certificate extensions are global). | |
sshHostAddress(value) | A host certificate principal: a DNS name (a leading *. is refused), or an IPv4/IPv6 address. | |
const sshHostResourceType | The resource type of an enrolled SSH host, ssh-host, named ssh-host/{host}, on which the forwarding actions are decided (SSH access). | |
sshKeyLine(blob, comment?) | An authorized_keys-style line for a key blob. | |
const sshKeyTypes | Public key algorithms accepted in certificates, with their certificate type names. | |
sshLogin(value) | A Unix login name, as certificate principals carry them: portable user names only. | |
const sshLoginAction | The action, ssh:login, decided for every host and login pair a user certificate is to name. Use it with iam.authorize or policies.simulate to check SSH access outside certificate issuance. | |
const sshLoginResourceType | The resource type of a host and login pair, ssh-login, named ssh-login/{host}/{login}, on which ssh:login is decided (SSH access). | |
sshSerial() | A random non-zero 63-bit serial (KRLs cannot revoke serial 0). | |
sshSigningKey(publicBlob, privatePkcs8) | Opens a stored authority key. | |
const STATUS_INVALID | The Token Status List value of a revoked credential (1). Compare statusAt results with it, STATUS_VALID (0), and STATUS_SUSPENDED. | |
const STATUS_LIST_JWT_TYPE | The typ of a signed Token Status List (statuslist+jwt), served at {issuer}/status/{listId}. | |
const STATUS_SUSPENDED | The Token Status List value of a suspended credential (2), which reinstate sets back to STATUS_VALID. | |
const STATUS_VALID | Status values of the Token Status List. | |
statusAt(bytes, index, bits) | Reads the status of index from a raw list of bits-bit entries (index 0 is the low bits of byte 0). | Verifiable credentials |
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. | Teams and departments |
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. | |
const threatRules | The rule catalog, in display order. | |
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. | |
const vcRequestAction | The action, vc:request, decided when a person requests a credential of a type for themselves, on credential-type/{name} (who gets credentials). | |
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 |
verifyEvidencePack(pack, keys) | Verifies an evidence pack offline, with the deployment's published evidence keys (compliance.evidenceKeys): the digest must match the pack's content and the signature must verify with the key it names. Needs no server. | Audit readiness for SOC 2 |
verifyHolderProof(proof, options) | Verifies an OpenID4VCI holder proof (typ: openid4vci-proof+jwt, the holder's public key in the jwk header): signature, aud (the credential issuer), freshness, and the nonce the issuer handed out. Returns the holder key and its RFC 7638 thumbprint. | |
verifySdJwt(value, options) | Verifies an SD-JWT VC or presentation: the issuer's signature (issuerKey resolves kid/iss), validity times, every disclosure against the signed digests, and, for presentations, the key-binding JWT (audience, nonce, freshness, sd_hash) with the holder key in cnf.jwk. Throws SdJwtError with the reason. | Verifiable credentials |
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. | Run in multiple regions |
@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. | Server API |
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. | Tokens and JWTs |
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. | Tokens and JWTs |
@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. | Access paths |
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. | Vue |
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). |
Better IAM is created by Sean Filimon
Last updated