Skip to main content

Auth SDK API

Exports: Ulda, SocketIoTransport and UldaError. Both ulda-auth and ulda-auth/browser expose the same API. The browser entry includes its dependencies.

See the usage guide for complete workflows and pipelines for internal steps.

Values and identifiers​

  • Resource IDs are strings matching [1-9][0-9]{0,39}: 1–40 decimal digits, no leading zero.
  • Content names are nonempty strings of at most 256 UTF-16 code units, unique within a master.
  • Modes are 'X' and 'S'. The master is always X.
  • Data may contain null, booleans, finite numbers, strings, dense arrays and plain objects, including null-prototype objects.
  • Undefined, bigint, functions, symbols, Date, custom prototypes, accessors, sparse arrays and cycles are rejected. The validator does not invoke getters or toJSON. Special own property names are copied as data.
  • A path is an array of strings or safe integer indices, at most 48 components. Array indices must be nonnegative existing indices. Intermediate path components must exist.

Data is defensively copied. Returned object copies may have a null prototype; use Object.hasOwn rather than inherited helpers.

Constructor​

const ulda = new Ulda(endpoint, options);

The constructor begins connection establishment. The standard transport accepts HTTPS URLs without credentials, query or fragment. HTTP is allowed only for an explicit loopback development connection.

OptionDefaultContract
timeout10000Integer milliseconds, 50–60000; used by the standard transport
allowInsecureLocalhostfalseAllows HTTP only for localhost, 127.0.0.1 or [::1]
reconnectDefault settings belowfalse disables automatic recovery; an object overrides settings
transportNew SocketIoTransportAn existing transport instance; its endpoint and transport options govern the connection

Unknown top-level Ulda options are rejected. When injecting a transport, configure its timeout and endpoint when constructing it.

Reconnect settings​

SettingDefaultAllowed values
maxAttempts5Integer 1–20
initialDelay500Integer milliseconds, at least 10 and no greater than maxDelay
maxDelay5000Integer milliseconds, at most 60000
jitter0.2Number from 0 to 1
budget30000Integer milliseconds, 50–300000

Automatic recovery starts only after a previously established connection disconnects unintentionally. The first failed ready is not retried automatically. Explicit reconnect uses the same bounded recovery mechanism, even when automatic recovery is disabled.

Properties and local reads​

MemberResult
readyPromise<void> for connection and Hello; updated when explicit reconnect starts
statusCurrent status string
dataReference tree for the open catalog
contextGenerationInternal reference-generation number; not a server revision
snapshot()Independent copy of all currently available content JSON, keyed by name
value(name, path = [])Independent copy of a content value or nested value
ref(name)Reference bound to the current content ID and session
on(event, listener)A function that removes that local listener and returns whether it was removed

These data reads require an open catalog but can read a retained snapshot while disconnected or in needsResync. They do not request network data and do not prove freshness.

Status values​

StatusMeaning
connectingInitial connection/Hello in progress
readyTransport is ready, no master is open
openA verified catalog is available; operation-specific guards still apply
disconnectedTransport is unavailable; a previously opened snapshot may remain readable
reconnectingA bounded connection recovery cycle is running
needsResyncAn integrity fault or unresolved state prevents normal writes
closedTerminal state; use a new instance

Use operation promises and status together. A transport-level ACK does not guarantee that every unrelated resource or pending operation is ready to write.

Session methods​

register​

register(password) → Promise<string>

Create a master and open its prepared local state after a valid Create ACK. Returns the assigned master ID. Password must be a nonempty string of at most 1024 UTF-16 code units. Its contents are not sent to the server.

The method awaits readiness and requires no open or opening master. It performs local key derivation, origin creation and encryption before Create. It does not reread its own successful Create.

If the request outcome is unknown, no successful master ID is returned. The server may hold an orphan resource. There is no ID-guessing or automatic Create retry.

connect​

connect(masterId, password) → Promise<DataTree>

Open an existing master and its referenced content. Requires no existing/opening master. Password rules match register.

The master, catalog and required content are verified before the new session is published. Returns the same kind of reference tree as ulda.data. Wrong credentials or corrupted ciphertext can both produce CRYPTO_FAILED.

A new concurrent integrity fault prevents the older read from opening the context. An explicit new connect performs a new read.

refresh​

refresh() → Promise<DataTree>

Read and verify the open master and its contents, then replace the working snapshot as a set. Does not advance chains or issue writes. Successful reads restore server subscriptions.

Active writes or recovery work can cause BUSY. Failure preserves the previous verified snapshot. Success can still leave status === 'needsResync' if an uncertain operation is unresolved.

Refresh accepts a newer authenticated snapshot without requiring missing intermediate chain history; see Security.

reconnect​

reconnect() → Promise<DataTree | undefined>

Reconnect, send Hello, and refresh if a master is open. Returns a data tree for an open catalog or undefined if only transport readiness is restored.

Concurrent calls join the existing cycle. Closing cancels it. Read/connect retries are bounded; writes are never replayed. Invalid data or an unresolved write can stop recovery rather than trigger another attempt.

close​

close() → Promise<void>

Close the instance. Repeated calls join the same close operation. Invalidates references, cancels SDK waits, releases private state, attempts a bounded session-close ACK if connected, then closes the transport.

It does not delete resources or reverse committed writes. Cleanup starts before waiting for the server. A late response cannot reopen the instance.

Content methods​

add​

add(name, value, mode = 'X') → Promise<AddResult>

Creates a content resource and adds one encrypted entry to the master.

{ ok: true, name, subscriptionReady }

The name must not already exist. There is no fixed content-entry count limit in a master. Encrypted catalog bytes, operation bytes and the server's admission budgets still apply; see the limits and capacity. Mode is fixed at creation.

The operation reserves an encrypted empty resource, then sends one atomic Update for the content and master. The reservation is a separate commit. subscriptionReady is the transport's connection state at completion, not a permanent delivery guarantee.

A retained known reservation may be continued explicitly on the same instance with the same input after conflict handling. A lost Create ID cannot be recovered that way. Normal methods are blocked when the catalog has an unresolved unknown outcome.

update​

update(name, value) → Promise<{ ok: true }>

Replace the entire content JSON. Equivalent to set(name, [], value). Queued per resource; the returned promise belongs to that write's ACK.

set​

set(name, path, value) → Promise<{ ok: true }>

Replace a nested value, or the whole content when path is empty. An object field at the final component may be new; parents must already exist. Arrays support replacement at existing indices.

remove​

remove(name, path) → Promise<{ ok: true }>

Remove an existing field or array element. Array elements are removed using splice semantics. An empty path is rejected; use delete(name) for the whole resource.

delete​

delete(name) → Promise<{ ok: true }>

Refresh the catalog and content, then atomically delete the selected content and update the master without its entry. It requires no competing local operation and can return BUSY.

Physical deletion affects any other catalog that references the same ID. The server cannot discover those encrypted references. Fresh reads do not lock out other writers; the server's witness check still decides whether the final batch can commit.

superDelete​

superDelete() → Promise<{ ok: true }>

Refresh and validate all referenced resources, delete the listed content and master in one atomic batch, then close the instance.

Invalid or missing required content can stop the operation before deletion. There is no forced deletion of an unreadable master/catalog through this method.

recoverContent​

recoverContent(name) → Promise<RecoveryResult>

Create a replacement from the last confirmed local copy, update one master entry, and preserve the old resource.

{ ok: true, previousId, id, sourceAge, reconciled }

sourceAge belongs to the old chain. reconciled means this explicit call verified a previously uncertain recovery update; it does not change the result of an earlier rejected promise.

Requires a verified local source, a live connection and no competing local writes. A retained recovery plan blocks normal writes until resolved or closed. See Recovery for all continuation rules.

References​

ulda.ref(name), ulda.data[name] and ulda.data.field(name) address the same content.

MemberBehavior
get()Read an independent JSON copy
toJSON()Same local read; used by explicit JSON serialization
update(value)Update the addressed node
delete()Remove the node; at content root, call ulda.delete
field(key)Address a child with a dynamic or reserved name
reference.key / reference[index]Address an ordinary child

Reserved reference members: get, update, delete, field, toJSON and then. Access data with these names through field. At data-tree level, use ref or data.field for field, toJSON and then. Symbol properties and automatic then access are not data references.

Direct assignment, the JavaScript delete operator and property definition are rejected. Reference objects do not behave like their primitive values; use get explicitly.

Old references fail with STALE_REFERENCE after their content is replaced/deleted or the session is invalidated. Reusing a name does not reuse its identity.

Events​

const unsubscribe = ulda.on('status', status => {
// Keep the handler synchronous, or handle its own asynchronous failures.
});

Synchronous listener exceptions are isolated from SDK processing. Returned promises from asynchronous listeners are not awaited; handle their rejections yourself.

EventPayload
statusA status string
change{ kind: 'updated', id } or { kind: 'updated' | 'deleted' | 'recovered', ids }
errorUldaError with a fixed code/message
traceImmutable client summary: time, phase='client', event, step, ids, count
reconnectImmutable phase plus applicable attempt, delayMs or code

Reconnect phases: waiting, attempt, restored, stopped, cancelled. Millisecond timestamps and durations are diagnostic metadata, not chain ages or server revisions.

change signals that application data may have changed. It contains no plaintext and is not emitted as a substitute for every method's promise. If a deletion closes the SDK, do not read a snapshot from the closed instance.

Errors​

UldaError extends Error. Its constructor takes a code string; inspect its code property when handling SDK failures.

Use error.code rather than matching message text. Some validation occurs before a promise is returned.

CodeMeaning / response
INVALID_INPUTInvalid local value, ID, name, path or option
INVALID_PACKETInvalid wire shape or binary representation
UNSUPPORTED_PROFILEUnsupported or noncanonical ULDA profile
CRYPTO_FAILEDAuthentication, decryption or resource identity failed
CLOSEDInstance has been closed
OFFLINETransport is unavailable
NOT_OPENNo master is open
UNKNOWN_OUTCOMEA write may have committed; do not replay automatically
CONFLICTWitness/state conflict; refresh and reconsider the intention
NOT_FOUNDRequested resource, content or path does not exist
EXISTSContent name is already present
NEEDS_RESYNCIntegrity/uncertain state blocks normal writes
ROLLBACKOlder state or different bytes at the same age rejected
LIMITA size, queue, resource or chain-age limit was exceeded
UNSUPPORTEDOperation is not supported by the current API/profile
SERVER_ERRORServer rejection not mapped to a more specific code
STALE_REFERENCEReference no longer addresses the same live context/resource
BUSYAn operation conflicts with active local work
TIMEOUTConnection/read/recovery deadline exceeded

For writes already sent, loss of an ACK is reported as UNKNOWN_OUTCOME rather than a definite timeout/rollback. Raw server error strings are not propagated.

SocketIoTransport​

An advanced export for configuring the transport and observing safe transport-level diagnostics:

import { Ulda, SocketIoTransport } from 'ulda-auth';

const transport = new SocketIoTransport(endpoint, { timeout: 10_000 });
const stopTrace = transport.on('trace', record => {
// IDs, sizes, fixed event codes and timings; no plaintext.
});
const ulda = new Ulda(endpoint, { transport });

Options: timeout, allowInsecureLocalhost and diagnostics (false by default). Enabling diagnostics allows optional ulda:diagnostic events from a compatible server. It is not an authentication option.

Members:

  • connected: boolean.
  • start({ signal }?): connect, returning Promise.
  • send(packet, { volatile, signal }?): internal SDK-created PacketHandle only.
  • disconnect(): intentional disconnect.
  • close(): terminal transport cleanup.
  • on(event, listener): remove-listener function.

Transport events are changed, disconnect, error and trace. changed contains IDs, ciphertext and public witnesses; it is below the SDK's decryption/chain-verification layer. It is not a verified application snapshot.

PacketHandle has no public constructor. A plain object supplied to send is not a supported way to bypass the SDK's encryption path. This boundary prevents accidental misuse; it does not sandbox hostile code in the same process.

Limits​

See the limits and capacity for numeric limits and the security policy for trust and memory boundaries. Type declarations describe the API but do not replace runtime validation.

Capacity and compatibility​

See Limits and capacity planning for SDK bounds, interacting server budgets, eager-loading costs, atomicity, timeouts and upgrades from 1.0.x.

TypeScript declarations​

Both package entry points include types for Ulda, references, events, operation results and SocketIoTransport. Read or download the full declarations. Runtime validation remains authoritative.


Reference for Auth SDK 1.1.0. Reviewed source.