wasm-inline
wasm-inline is a module in @cipherstash/stack. TypeScript API reference with its signature, parameters, and usage.
wasm-inline
Classes
AccessKeyStrategy
Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:106
An auth strategy that uses a static access key for service-to-service
or CI/CD authentication, scoped to a single workspace identified by a
CRN. The region is derived from the CRN, so there's no separate
region argument and no chance of the strategy operating against a
region the caller didn't expect.
Every issued token's workspace JWT claim is verified against the
CRN's workspace ID. A mismatch fails the getToken() call with an
AuthError whose code is "WORKSPACE_MISMATCH" — the strategy
never silently lets a multi-workspace access key operate on the
wrong workspace.
Methods
create()
static create(
workspaceCrn,
accessKey,
options?): Result<AccessKeyStrategy, AuthFailure>;Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:122
Create a new AccessKeyStrategy for the given workspace CRN and
access key.
The CRN format is crn:<region>:<workspace-id> (e.g.
"crn:ap-southeast-2.aws:ZVATKW3VHMFG27DY"). Region is parsed from
the CRN and used for service discovery; the workspace ID is used
to verify every issued token belongs to the right workspace.
Pass options.store to back the strategy with a persistent cache —
see TokenStore and the
`@cipherstash/auth/cookies`
helper.
Parameters
workspaceCrn
string
accessKey
string
options?
AccessKeyStrategyOptions
Returns
Result<AccessKeyStrategy, AuthFailure>
getToken()
getToken(): Promise<GetTokenResult>;Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:128
Retrieve a valid access token, refreshing or re-authenticating as needed.
Returns
Promise<GetTokenResult>
free()
free(): void;Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:130
Release the underlying wasm resources.
Returns
void
OidcFederationStrategy
Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:160
An auth strategy that federates a third-party OIDC JWT (Clerk, Supabase, …)
into a CipherStash CTS service token via /api/authorise.
Methods
create()
static create(
workspaceCrn,
getJwt,
options?): Result<OidcFederationStrategy, AuthFailure>;Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:174
Create an OidcFederationStrategy for the given workspace CRN.
The CRN format is crn:<region>:<workspace-id> (e.g.
"crn:ap-southeast-2.aws:ZVATKW3VHMFG27DY"). Region is parsed from the
CRN and used for service discovery; the workspace ID is used to verify
every federated token belongs to the right workspace.
getJwt must return the current third-party OIDC JWT (it is re-invoked
on every re-federation). Pass options.store to back the strategy with a
persistent cache — see TokenStore.
Parameters
workspaceCrn
string
getJwt
OidcProvider
options?
OidcFederationStrategyOptions
Returns
Result<OidcFederationStrategy, AuthFailure>
getToken()
getToken(): Promise<GetTokenResult>;Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:180
Retrieve a valid CTS service token, federating or re-federating as needed.
Returns
Promise<GetTokenResult>
free()
free(): void;Defined in: ../../../node_modules/.bun/@[email protected]/node_modules/@cipherstash/auth/wasm-inline.d.ts:182
Release the underlying wasm resources.
Returns
void
WasmEncryptionClient
Defined in: wasm-inline.ts:731
WASM encryption client. Returned by Encryption.
Wraps an opaque wasmNewClient handle and exposes encrypt, decrypt,
isEncrypted, encryptQuery / encryptQueryBulk for minting v3 query
terms (#662, which made searchable encryption reachable on the edge),
bulkEncrypt / bulkDecrypt for single-round-trip list reads and writes
(#737), and the model helpers encryptModel / decryptModel /
bulkEncryptModels / bulkDecryptModels (#742).
Every fallible method returns a Result
{ data } | { failure }, with failure.type drawn from
EncryptionErrorTypes — the same contract the native entry honours, and
the one AGENTS.md states outright: "Operations return { data } or
{ failure }. Preserve this shape and error type values in
EncryptionErrorTypes."
This entry THREW until #741. That was drift, not a design decision: nothing
about WASM prevents it (@byteslice/result is already bundled into
dist/wasm-inline.js — see tsup.config.ts noExternal), and the
divergence just meant edge code had to be written in a different shape from
every other surface, with failures that were easy to miss. Aligned before
1.0 so it never had to be a breaking change afterwards.
isEncrypted is the one exception, and stays a plain boolean: it is a
pure predicate with nothing to fail at, exactly as on the native entry.
The model helpers run the SAME traversal the native entry uses
(@/encryption/helpers/model-traversal — shared, not ported, so the two
entries cannot drift on which fields get encrypted), and each call is one
ZeroKMS round trip regardless of how many fields or models it covers. What
still differs from the native surface is deliberate and local: failures come
back as this entry's { failure } Results (rather than a thenable operation
with .audit()).
There is also no .withLockContext() here, and that one is a gap, not a
design decision (#797). An earlier version of this comment said
identity-bound encryption is "configured at client construction via
config.authStrategy instead" (#663 context). That is wrong, and the
conflation is worth naming because it is the one people arrive with:
an auth strategy decides WHO THE CLIENT IS; a lock context decides WHO CAN
RETRIEVE A VALUE'S DATA KEY (the claim from the encrypting caller's service
token is bound to the key, and retrieval requires presenting the same
claim). They are orthogonal, and only the first exists on this entry.
The consequences are silent, which is why they are stated here rather than
left to a failed decrypt: values written from this entry carry no identity
condition on key retrieval — any client with keyset access can decrypt
them — even when the client is authenticated as an end user, and this
entry cannot read anything the native entry wrote under a lock context,
since key retrieval requires the same claim. skills/stash-auth is
canonical for the model; skills/stash-edge documents this entry's gap.
The binding accepts a lock context on both paths — lockContext is an
option field on the single calls and per-payload-item on the bulk ones — so
closing this is plumbing rather than a new capability. It is not plumbed
here yet, and shipping it would want a live round-trip test first: a wrong
or missing claim surfaces as a failed decrypt, not a key error.
Construct via Encryption — the constructor is private to prevent callers from wrapping arbitrary objects in this type.
Properties
requiresTableForDecrypt
readonly requiresTableForDecrypt: true = true;Defined in: wasm-inline.ts:748
This client's decryptModel / bulkDecryptModels REQUIRE the table — they
resolve date fields from a per-table map and throw without it. The native
clients derive the table from the payloads instead, so callers that hold a
client structurally cannot tell the two apart.
Declared rather than sniffed so the capability is a stated fact, not a guess about arity or constructor name (#772 review, finding 10).
This does NOT imply the entry cannot serve a legacy EQL v2 read. It once
did: encryptedDynamoDB used to omit the table on that path, reaching
requireTable with undefined. It now forwards the registered v3 table on
every read, v2 storage included — the reconstructor map is keyed by the
current schema either way, and protect-ffi's decrypt accepts both wire
generations regardless of the client's eqlVersion.
Methods
encrypt()
encrypt(plaintext, opts): Promise<WasmResult<EncryptedPayload>>;Defined in: wasm-inline.ts:806
Parameters
plaintext
opts
Returns
Promise<WasmResult<EncryptedPayload>>
decrypt()
decrypt(encrypted): Promise<WasmResult<WasmPlaintext>>;Defined in: wasm-inline.ts:837
Decrypt a single stored payload, resolving to the plaintext union unchanged.
A date / timestamp column comes back as the string it was stored as,
not a Date — where decryptModel(row, table) reconstructs it via
datePropertyPaths. Same boundary the native client draws, and for
the same reason: reconstruction is a property of the MODEL path, which is
handed a table to read cast_as from. Not because the identity is missing
— every payload carries i: { t, c } — but because this method's declared
plaintext union excludes Date, and returning one would make the type a
lie (#779). Read through the model helpers, or new Date(value) yourself.
Parameters
encrypted
EncryptedPayload
Returns
Promise<WasmResult<WasmPlaintext>>
isEncrypted()
isEncrypted(value): boolean;Defined in: wasm-inline.ts:850
Parameters
value
unknown
Returns
boolean
encryptQuery()
encryptQuery(plaintext, opts): Promise<WasmResult<
| EncryptedQuery
| null>>;Defined in: wasm-inline.ts:929
Encrypt a QUERY TERM (search needle) for a queryable v3 column — equality, free-text match, ORE range, or JSON containment/selector.
The returned term is ciphertext-free: it is matched against stored
envelopes, never decrypted, so it is safe to log-scrub less aggressively
than storage payloads (though it still derives from the plaintext).
Interpolate it as a parameter and cast to the column's
eql_v3.query_<domain> type to reach the indexed operators — the domain
suffix mirrors the storage domain (eql_v3_text_eq →
eql_v3.query_text_eq; irregular: eql_v3_json_search → eql_v3.query_json).
Parameters
plaintext
The search needle. null/undefined returns null
without contacting ZeroKMS (nothing to search for), mirroring the
native client.
opts
Table, column, and (optionally) which index to target — see WasmEncryptQueryOptions.queryType for the inference rules.
Returns
Promise<WasmResult<
| EncryptedQuery
| null>>
{ data } with the v3 query term (or null for null
plaintext), or { failure } when the requested queryType isn't
configured on the column, the column has no indexes at all, the value
fails the same pre-flight validation the native client runs (NaN /
Infinity / out-of-int64 bigint, or a numeric value against a
freeTextSearch index), or encryption fails.
Examples
const term = await client.encryptQuery("[email protected]", {
table: users, column: users.email, queryType: "equality",
})
if (term.failure) throw new Error(term.failure.message)
// postgres-js — bind the unwrapped term, not the Result:
sql`SELECT * FROM users
WHERE email = ${term.data}::jsonb::eql_v3.query_text_eq`const term = await client.encryptQuery("needle", {
table: users, column: users.bio, queryType: "freeTextSearch",
})
if (term.failure) throw new Error(term.failure.message)
sql`SELECT * FROM users
WHERE eql_v3.matches(bio, ${term.data}::jsonb::eql_v3.query_text_search)`const term = await client.encryptQuery(42, {
table: users, column: users.age, queryType: "orderAndRange",
})
if (term.failure) throw new Error(term.failure.message)
sql`SELECT * FROM users
WHERE eql_v3.gte(age, ${term.data}::jsonb::eql_v3.query_integer_ord)`// Object value → containment needle (a v3 envelope):
const contains = await client.encryptQuery({ role: "admin" }, {
table: users, column: users.prefs, queryType: "searchableJson",
})
if (contains.failure) throw new Error(contains.failure.message)
sql`SELECT * FROM users
WHERE prefs @> ${contains.data}::jsonb::eql_v3.query_json`
// String value → JSONPath selector. NOTE: v3 has no encrypted-selector
// envelope — this returns the BARE selector-hash string, bound as the
// text argument of -> / ->>:
const selector = await client.encryptQuery("$.role", {
table: users, column: users.prefs, queryType: "searchableJson",
})
if (selector.failure) throw new Error(selector.failure.message)
sql`SELECT prefs -> ${selector.data} FROM users`encryptQueryBulk()
encryptQueryBulk(terms): Promise<WasmResult<(
| EncryptedQuery
| null)[]>>;Defined in: wasm-inline.ts:971
Batch form of encryptQuery — one ZeroKMS round trip for many terms, which is the shape query builders want (encrypt every needle in a WHERE clause together).
Position-stable: the result array is index-aligned with terms, and a
null/undefined value yields null at the same index (an all-null
batch short-circuits without calling ZeroKMS). Terms may mix query
types and columns freely.
Parameters
terms
readonly WasmQueryTerm[]
The needles to encrypt; see WasmQueryTerm.
Returns
Promise<WasmResult<(
| EncryptedQuery
| null)[]>>
{ data } with an index-aligned array of v3 query terms (null
per null value), or { failure } — the first invalid term aborts the
batch, as encryptQuery.
Example
const terms = await client.encryptQueryBulk([
{ value: "[email protected]", table: users, column: users.email,
queryType: "equality" },
{ value: "needle", table: users, column: users.bio,
queryType: "freeTextSearch" },
])
if (terms.failure) throw new Error(terms.failure.message)
const [emailEq, bioMatch] = terms.databulkEncrypt()
bulkEncrypt(items): Promise<WasmResult<(EncryptedPayload | null)[]>>;Defined in: wasm-inline.ts:1040
Encrypt many storage values in ONE ZeroKMS round trip.
Without this, an edge function writing N rows pays N round trips — the
property AGENTS.md calls out ("prefer bulk operations to exercise
ZeroKMS bulk speed") was unreachable from the WASM entry entirely (#737).
Position-stable: the result is index-aligned with items, and a
null/undefined plaintext yields null at the same index without
being sent to ZeroKMS (an all-null batch short-circuits entirely).
Entries may mix tables and columns freely — see WasmBulkPlaintext.
How this differs from the native bulkEncrypt
The failure shape is the SAME — { data } | { failure }, per
AGENTS.md — but the batch shape differs: the Node entry takes one
column for the whole batch and wraps values in { id, plaintext }
envelopes, where this takes per-item routing and plain values.
That divergence is about capability, not convention. Per-item routing is
what makes the round-trip saving real (one call covers several columns
across many rows), and the id bookkeeping buys nothing once positions
are stable — the FFI's EncryptPayload has no id field, so the native
one is dropped at the boundary anyway.
Parameters
items
readonly WasmBulkPlaintext[]
Values to encrypt, each with its own table and column.
Returns
Promise<WasmResult<(EncryptedPayload | null)[]>>
{ data } with an index-aligned array of storage payloads
(null per null input), or { failure }. The batch is all-or-nothing:
ZeroKMS rejects the call as a whole, so there is no per-item error to
report (unlike bulkDecrypt, whose FFI primitive IS fallible).
Example
const rows = [{ email: "[email protected]", bio: "hi" }, { email: "[email protected]", bio: "yo" }]
const encrypted = await client.bulkEncrypt(
rows.flatMap((r) => [
{ plaintext: r.email, table: users, column: users.email },
{ plaintext: r.bio, table: users, column: users.bio },
]),
)
if (encrypted.failure) throw new Error(encrypted.failure.message)
// encrypted.data[0] = email of row 0, [1] = bio of row 0, …bulkDecrypt()
bulkDecrypt(ciphertexts): Promise<WasmResult<WasmPlaintext[]>>;Defined in: wasm-inline.ts:1110
Decrypt many stored payloads in ONE ZeroKMS round trip.
This is the half that matters most on the edge: rendering a list of N encrypted rows cost N round trips before this existed, which is what made list endpoints impractical on Deno / Workers (#737).
Position-stable, same contract as bulkEncrypt: index-aligned with
ciphertexts, null/undefined passes through as null without
reaching ZeroKMS, and an all-null batch short-circuits.
Partial failure
The underlying primitive is decryptBulkFallible, which reports success
or failure PER ITEM — one undecryptable row does not fail the call at the
FFI level. Any failure still collapses the whole call into a single
{ failure }, but its message names EVERY failed index and reason rather
than surfacing the first and discarding the rest. So a caller debugging
one bad row in a page of 50 learns which row, and that the other 49 were
fine.
(A per-item Result[] would preserve the partial success too, and is
worth considering if callers ask for it — but it is a different return
type from every other method here, so it is not the default.)
No date reconstruction
Same boundary as decrypt: date-like columns arrive as their stored
strings, not Date values. Prefer bulkDecryptModels with the table
when you want the column's declared plaintext type back (#779).
Parameters
ciphertexts
readonly (EncryptedPayload | null | undefined)[]
Stored payloads; null/undefined entries allowed.
Returns
Promise<WasmResult<WasmPlaintext[]>>
{ data } with an index-aligned array of plaintexts (null per
null input), or { failure } naming each failing index and its reason.
Example
const rows = await sql`SELECT email FROM users LIMIT 50`
const emails = await client.bulkDecrypt(rows.map((r) => r.email))
if (emails.failure) throw new Error(emails.failure.message)
// one ZeroKMS call, not 50encryptModel()
encryptModel<Table, T>(model, table): Promise<WasmResult<V3EncryptedModel<Table, T>>>;Defined in: wasm-inline.ts:1188
Encrypt a model's schema-declared fields in ONE ZeroKMS round trip.
Walks model against table's columns — matched by JS property name,
nested fields via a column's dotted path ('profile.ssn') — and encrypts
exactly the declared fields. Everything else passes through untouched,
and a null/undefined schema field is preserved as-is without
reaching ZeroKMS. The traversal is the native entry's own, shared from
@/encryption/helpers/model-traversal (#742): a column added to the
schema is picked up by construction, instead of by remembering to extend
a hand-written bulkEncrypt mapping — the failure mode of that mapping
is a field that silently persists in PLAINTEXT.
Date plaintexts (date/timestamp domains) are sent as ISO-8601 strings —
WasmPlaintext carries no Date across the WASM serde boundary —
and decryptModel rebuilds them into Date values on the way out.
Type Parameters
Table
Table extends AnyV3Table
T
T extends Record<string, unknown>
Parameters
model
V3ModelInput<Table, T>
table
Table
Returns
Promise<WasmResult<V3EncryptedModel<Table, T>>>
Example
const row = await client.encryptModel(
{ id: 1, email: "[email protected]", verified: true },
users,
)
if (row.failure) throw new Error(row.failure.message)
// row.data = { id: 1, email: <EQL envelope>, verified: true }bulkEncryptModels()
bulkEncryptModels<Table, T>(models, table): Promise<WasmResult<V3EncryptedModel<Table, T>[]>>;Defined in: wasm-inline.ts:1214
Encrypt many models in ONE ZeroKMS round trip — encryptModel's traversal applied per model, with every collected field across every model batched into a single FFI call. N models × M columns is still one crossing, the same economics as bulkEncrypt.
The result array is index-aligned with models. An empty input returns
{ data: [] } without contacting ZeroKMS.
Type Parameters
Table
Table extends AnyV3Table
T
T extends Record<string, unknown>
Parameters
models
V3ModelInput<Table, T>[]
table
Table
Returns
Promise<WasmResult<V3EncryptedModel<Table, T>[]>>
decryptModel()
decryptModel<Table, T>(model, table): Promise<WasmResult<V3ModelInput<Table, T>>>;Defined in: wasm-inline.ts:1250
Decrypt every encrypted payload in a model, in ONE ZeroKMS round trip.
Schema-blind on the way in — any value that IS an EQL envelope is
decrypted, wherever it nests; everything else (nulls included) passes
through untouched, and the caller's model is never mutated. Schema-aware
on the way out: table's date-like columns (date / timestamp domains,
matched by JS property name) are rebuilt into Date values, so a value
this client encrypted round-trips Date → Date. table must be one the
client was initialized with, else the call fails (as the native client).
Partial failure
Built on the same per-item-fallible primitive as bulkDecrypt:
one undecryptable field does not mask the rest. Any failure collapses to
a single { failure } whose message names EVERY failed field by its
path in the model (e.g. profile.ssn), with its per-item code.
Type Parameters
Table
Table extends AnyV3Table
T
T extends Record<string, unknown>
Parameters
model
T
table
Table
Returns
Promise<WasmResult<V3ModelInput<Table, T>>>
bulkDecryptModels()
bulkDecryptModels<Table, T>(models, table): Promise<WasmResult<V3ModelInput<Table, T>[]>>;Defined in: wasm-inline.ts:1272
Decrypt many models in ONE ZeroKMS round trip — decryptModel
across a list, which is the shape a page of database rows arrives in.
The result array is index-aligned with models; an empty input returns
{ data: [] } without contacting ZeroKMS. Failures are reported for
every bad field across the whole batch, labelled [model <i>] <field>.
Type Parameters
Table
Table extends AnyV3Table
T
T extends Record<string, unknown>
Parameters
models
T[]
table
Table
Returns
Promise<WasmResult<V3ModelInput<Table, T>[]>>
Type Aliases
WasmPlaintext
type WasmPlaintext =
| string
| number
| bigint
| boolean
| null
| Record<string, unknown>
| WasmPlaintext[];Defined in: wasm-inline.ts:191
The plaintext shape accepted by encrypt and returned by decrypt.
Mirrors protect-ffi's JsPlaintext (recursive: arrays of any of
these are valid), plus bigint for int8 columns. Re-defined here so
the wasm-inline .d.ts doesn't pull in the Node-only protect-ffi types.
bigint is carried natively across the wasm boundary by protect-ffi
0.28's Rust encode_plaintext (which i64-bounds-checks on encrypt and
builds a js_sys::BigInt on decrypt), so widening the type here is all
the SDK needs to accept/return bigint on the wasm entry point.
WasmClientConfig
type WasmClientConfig = {
clientId: string;
clientKey: string;
eqlVersion?: never;
} &
| {
workspaceCrn: string;
accessKey: string;
authStrategy?: never;
strategy?: never;
}
| {
workspaceCrn?: string;
accessKey?: never;
authStrategy: WasmAuthStrategy;
strategy?: WasmAuthStrategy;
}
| {
workspaceCrn?: string;
accessKey?: never;
authStrategy?: never;
strategy: WasmAuthStrategy;
};Defined in: wasm-inline.ts:221
Config for Encryption on the WASM entry point.
The workspace CRN is the single source of truth for workspace
identity and deployment region — matching the Node entry and
protect-ffi 0.25+, which read CS_WORKSPACE_CRN and no longer
consult a separate CS_REGION. The CRN is passed straight to the
underlying AccessKeyStrategy, which derives the region from it, so
there is no region field to keep in sync.
For service-to-service / CI use, pass accessKey plus the workspace
clientId / clientKey and we construct an AccessKeyStrategy for
you. To plug in a custom token store (cookies on Supabase Edge, KV on
Cloudflare Workers, …) or to bind encryption to an end user, build the
strategy yourself — AccessKeyStrategy or OidcFederationStrategy —
and hand it to config.authStrategy instead. A pre-built strategy
already carries the CRN, so workspaceCrn is optional on that path.
Mirrors the Node ClientConfig: authStrategy is the documented field,
strategy is retained as a deprecated alias (see below).
Type Declaration
clientId
clientId: string;Workspace client identifier — required by the WASM client.
clientKey
clientKey: string;Workspace client key — required by the WASM client.
eqlVersion?
optional eqlVersion: never;Removed: this entry always emits EQL v3. Declared as never rather than
omitted because excess-property checking — the only thing that caught a
leftover eqlVersion — fires on FRESH object literals alone. A shared
config const, which is what a v2 → v3 migration actually holds, therefore
type-checked clean and then hit the runtime guard in Encryption.
On the shared base so it applies across all three auth arms below; a copy
per arm would drift. Mirrors ClientConfig.eqlVersion on the native entry,
whose guard this one is a byte-for-byte mirror of — the type is defence in
depth for the JS/JSON callers that bypass it, not a replacement.
As on the native entry, ?: never still admits eqlVersion: undefined
without exactOptionalPropertyTypes (not enabled in this repo) and cannot
be made to reject it, so the runtime tolerates that one value and rejects
every real one.
WasmAuthStrategy
type WasmAuthStrategy =
| AccessKeyStrategy
| OidcFederationStrategy;Defined in: wasm-inline.ts:303
Any auth strategy accepted on the WASM path. Both expose
getToken(): Promise<Result<TokenResult, AuthFailure>> — as of
@cipherstash/auth 0.41 the token is wrapped in a @byteslice/result
envelope. @cipherstash/protect-ffi 0.28+ unwraps that envelope (reading
.data.token, surfacing .failure) inside its WASM newClient; 0.27 read
.token off the envelope and saw undefined, so keep the ffi floor at 0.28.
- AccessKeyStrategy — static M2M / CI access key.
- OidcFederationStrategy — federates an end-user OIDC JWT into a CTS service token, for per-user identity-bound encryption.
WasmEncryptionConfig
type WasmEncryptionConfig = {
schemas: readonly [AnyV3Table, ...AnyV3Table[]];
config: WasmClientConfig;
};Defined in: wasm-inline.ts:305
Properties
schemas
schemas: readonly [AnyV3Table, ...AnyV3Table[]];Defined in: wasm-inline.ts:320
One or more EQL v3 tables, authored with types / encryptedTable from
this entry. The WASM entry is EQL v3 only.
readonly (not the mutable tuple this once was) for the same reason the
native entry was widened in A-4: a mutable tuple rejects every shape that
is not an array literal — a shared export const all: AnyV3Table[], a
ReadonlyArray, anything spread. But non-emptiness stays HERE rather than
moving entirely onto the Encryption overloads: a loose
readonly AnyV3Table[] on the exported type laundered an empty set past
both overloads, because NonEmptyV3<readonly AnyV3Table[]> resolves
S['length'] to number, not 0. A config object built once and passed
around — precisely what this type exists for — then reached the runtime
throw with a clean typecheck. The overloads still accept widened arrays
passed INLINE, which is the case A-4 was actually about.
config
config: WasmClientConfig;Defined in: wasm-inline.ts:321
WasmEncryptOptions
type WasmEncryptOptions = {
table: AnyV3Table;
column: AnyEncryptedV3Column;
};Defined in: wasm-inline.ts:335
Properties
table
table: AnyV3Table;Defined in: wasm-inline.ts:336
column
column: AnyEncryptedV3Column;Defined in: wasm-inline.ts:337
WasmEncryptQueryOptions
type WasmEncryptQueryOptions = {
table: AnyV3Table;
column: WasmQueryableV3Column;
queryType?: QueryTypeName;
};Defined in: wasm-inline.ts:352
Options for WasmEncryptionClient.encryptQuery.
The column must be a QUERYABLE v3 column (authored via the types.*
factories re-exported from this entry) — storage-only columns like
types.Text with no indexes have nothing to query.
Properties
table
table: AnyV3Table;Defined in: wasm-inline.ts:354
The encryptedTable(...) the column belongs to.
column
column: WasmQueryableV3Column;Defined in: wasm-inline.ts:356
The queryable v3 column the term targets, e.g. users.email.
queryType?
optional queryType: QueryTypeName;Defined in: wasm-inline.ts:375
Which of the column's indexes the term targets:
'equality'— exact match (uniqueindex;=/IN)'freeTextSearch'— fuzzy token match (matchindex; one-sided — a match may be a false positive, a non-match never is)'orderAndRange'— comparisons and ranges (oreindex;<>BETWEEN/ORDER BY)'searchableJson'— encrypted JSON (ste_vecindex): a string value is treated as a JSONPath selector ('$.user.email'), any other value as a containment needle ({ role: 'admin' })
Omit to infer from the column's configured indexes (priority:
unique > match > ore > ste_vec, matching the native client) —
unambiguous for single-index columns like types.TextEq, but be
explicit for multi-index domains like types.TextSearch (which
carries all three scalar indexes).
WasmQueryTerm
type WasmQueryTerm = WasmEncryptQueryOptions & {
value: WasmPlaintext;
};Defined in: wasm-inline.ts:384
One term for WasmEncryptionClient.encryptQueryBulk — the
WasmEncryptQueryOptions plus the plaintext needle. A null
value yields null at the same position in the result (nothing to
search for).
Type Declaration
value
value: WasmPlaintext;WasmBulkPlaintext
type WasmBulkPlaintext = {
plaintext: | WasmPlaintext
| undefined;
table: AnyV3Table;
column: AnyEncryptedV3Column;
};Defined in: wasm-inline.ts:403
One storage value in a WasmEncryptionClient.bulkEncrypt batch.
Each entry carries its OWN table and column, rather than the batch taking a
single WasmEncryptOptions the way WasmEncryptionClient.encrypt does.
That mirrors WasmQueryTerm — and it is what makes the round-trip
saving worth having: rendering a page of rows means encrypting several
columns across many rows, and a single-column batch would still cost one
ZeroKMS call per column. The FFI's EncryptPayload is per-item
({ plaintext, table, column }), so mixing is free at the boundary.
(The native entry's bulkEncrypt takes one column for the whole batch and
wraps values in { id, plaintext } envelopes. This surface does neither —
see WasmEncryptionClient.bulkEncrypt for why.)
Properties
plaintext
plaintext:
| WasmPlaintext
| undefined;Defined in: wasm-inline.ts:415
The value to encrypt. null/undefined yields null at this index
without reaching ZeroKMS.
undefined is admitted explicitly — unlike WasmQueryTerm.value,
which is WasmPlaintext alone. Both are guarded identically at runtime,
but the shapes fed to them differ: a query needle is written by hand,
whereas a bulk batch is mapped straight off database rows, where an
absent column is undefined. Typing it out would force ?? null at
every call site to satisfy a check the runtime does anyway.
table
table: AnyV3Table;Defined in: wasm-inline.ts:416
column
column: AnyEncryptedV3Column;Defined in: wasm-inline.ts:417
WasmResult
type WasmResult<T> =
| {
data: T;
failure?: never;
}
| {
data?: never;
failure: EncryptionError;
};Defined in: wasm-inline.ts:444
The { data } | { failure } envelope every fallible method here returns.
Structurally identical to @byteslice/result's Result<T, EncryptionError>
— which is what withResult actually produces — but declared LOCALLY on
purpose, for the same reason WasmPlaintext re-declares protect-ffi's
JsPlaintext: @byteslice/result is bundled into dist/wasm-inline.js
(tsup noExternal), so it is not a package an edge consumer can resolve.
Re-exporting its type put import { Result } from '@byteslice/result' at the
top of the emitted .d.ts, which a Deno consumer cannot resolve at all — the
e2e import map maps only the three /wasm-inline subpaths.
Declaring it here keeps the published types self-contained.
Type Parameters
T
T
Functions
isEncrypted()
function isEncrypted(value): boolean;Defined in: wasm-inline.ts:165
Re-exported convenience predicate — same as the raw protect-ffi one.
Parameters
value
unknown
Returns
boolean
Encryption()
Call Signature
function Encryption<S>(config): Promise<WasmEncryptionClient>;Defined in: wasm-inline.ts:1460
Initialize a WASM-backed encryption client.
Mirrors the Node entry's import('./encryption').Encryption factory, but constructs the protect-ffi client via the WASM strategy API. Use from Deno / Edge / Workers / Bun.
Type Parameters
S
S extends readonly [AnyV3Table, AnyV3Table]
Parameters
config
schemas
S
config
Returns
Promise<WasmEncryptionClient>
Call Signature
function Encryption<S>(config): Promise<WasmEncryptionClient>;Defined in: wasm-inline.ts:1466
Initialize a WASM-backed encryption client.
Mirrors the Node entry's import('./encryption').Encryption factory, but constructs the protect-ffi client via the WASM strategy API. Use from Deno / Edge / Workers / Bun.
Type Parameters
S
S extends readonly AnyV3Table[]
Parameters
config
schemas
NonEmptyV3<S>
config
Returns
Promise<WasmEncryptionClient>
toWasmFfiPlaintext()
function toWasmFfiPlaintext(value): unknown;Defined in: wasm-inline.ts:1625
Normalise a value for the wasm serde boundary, applied at EVERY encrypt/query crossing (#742 review — previously only the model path did this).
A JS Date has no enumerable own properties, so wasm-bindgen carries it
across as {} — silent corruption of every date/timestamp column.
Serialise it to RFC 3339 (which protect-ffi's parse_naive_date accepts for
both casts, yielding the same canonical value as the native Date-object
path) and reject an invalid Date rather than emit "Invalid Date".
WasmPlaintext excludes Date so TS callers are already stopped; this is
the runtime guard for plain-JS callers, the same belt-and-braces rationale
assertValidNumericValue uses on the numeric path. Everything else passes
through unchanged.
Parameters
value
unknown
Returns
unknown
References
AnyEncryptedV3Column
Re-exports AnyEncryptedV3Column
EncryptedV3TableColumn
Re-exports EncryptedV3TableColumn
EqlTypeForColumn
Re-exports EqlTypeForColumn
JsonDocument
Re-exports JsonDocument
JsonValue
Re-exports JsonValue
PlaintextForColumn
Re-exports PlaintextForColumn
QueryCapabilities
Re-exports QueryCapabilities
QueryTypesForColumn
Re-exports QueryTypesForColumn
EncryptedBigintColumn
Re-exports EncryptedBigintColumn
EncryptedBigintEqColumn
Re-exports EncryptedBigintEqColumn
EncryptedBigintOrdColumn
Re-exports EncryptedBigintOrdColumn
EncryptedBigintOrdOreColumn
Re-exports EncryptedBigintOrdOreColumn
EncryptedBooleanColumn
Re-exports EncryptedBooleanColumn
EncryptedDateColumn
Re-exports EncryptedDateColumn
EncryptedDateEqColumn
Re-exports EncryptedDateEqColumn
EncryptedDateOrdColumn
Re-exports EncryptedDateOrdColumn
EncryptedDateOrdOreColumn
Re-exports EncryptedDateOrdOreColumn
EncryptedDoubleColumn
Re-exports EncryptedDoubleColumn
EncryptedDoubleEqColumn
Re-exports EncryptedDoubleEqColumn
EncryptedDoubleOrdColumn
Re-exports EncryptedDoubleOrdColumn
EncryptedDoubleOrdOreColumn
Re-exports EncryptedDoubleOrdOreColumn
EncryptedIntegerColumn
Re-exports EncryptedIntegerColumn
EncryptedIntegerEqColumn
Re-exports EncryptedIntegerEqColumn
EncryptedIntegerOrdColumn
Re-exports EncryptedIntegerOrdColumn
EncryptedIntegerOrdOreColumn
Re-exports EncryptedIntegerOrdOreColumn
EncryptedJsonColumn
Re-exports EncryptedJsonColumn
EncryptedNumericColumn
Re-exports EncryptedNumericColumn
EncryptedNumericEqColumn
Re-exports EncryptedNumericEqColumn
EncryptedNumericOrdColumn
Re-exports EncryptedNumericOrdColumn
EncryptedNumericOrdOreColumn
Re-exports EncryptedNumericOrdOreColumn
EncryptedRealColumn
Re-exports EncryptedRealColumn
EncryptedRealEqColumn
Re-exports EncryptedRealEqColumn
EncryptedRealOrdColumn
Re-exports EncryptedRealOrdColumn
EncryptedRealOrdOreColumn
Re-exports EncryptedRealOrdOreColumn
EncryptedSmallintColumn
Re-exports EncryptedSmallintColumn
EncryptedSmallintEqColumn
Re-exports EncryptedSmallintEqColumn
EncryptedSmallintOrdColumn
Re-exports EncryptedSmallintOrdColumn
EncryptedSmallintOrdOreColumn
Re-exports EncryptedSmallintOrdOreColumn
EncryptedTextColumn
Re-exports EncryptedTextColumn
EncryptedTextEqColumn
Re-exports EncryptedTextEqColumn
EncryptedTextMatchColumn
Re-exports EncryptedTextMatchColumn
EncryptedTextOrdColumn
Re-exports EncryptedTextOrdColumn
EncryptedTextOrdOreColumn
Re-exports EncryptedTextOrdOreColumn
EncryptedTextSearchColumn
Re-exports EncryptedTextSearchColumn
EncryptedTimestampColumn
Re-exports EncryptedTimestampColumn
EncryptedTimestampEqColumn
Re-exports EncryptedTimestampEqColumn
EncryptedTimestampOrdColumn
Re-exports EncryptedTimestampOrdColumn
EncryptedTimestampOrdOreColumn
Re-exports EncryptedTimestampOrdOreColumn
TEXT_SEARCH_EQL_TYPE
Re-exports TEXT_SEARCH_EQL_TYPE
AnyV3Table
Re-exports AnyV3Table
ColumnsOf
Re-exports ColumnsOf
InferEncrypted
Re-exports InferEncrypted
InferPlaintext
Re-exports InferPlaintext
QueryableColumnsOf
Re-exports QueryableColumnsOf
V3DecryptedModel
Re-exports V3DecryptedModel
V3EncryptedModel
Re-exports V3EncryptedModel
V3ModelInput
Re-exports V3ModelInput
buildEncryptConfig
Re-exports buildEncryptConfig
EncryptedTable
Re-exports EncryptedTable
encryptedTable
Re-exports encryptedTable
types
Re-exports types
EncryptionError
Re-exports EncryptionError
EncryptionErrorTypes
Re-exports EncryptionErrorTypes
Encrypted
Re-exports Encrypted