js/wasm api

Complete API reference for the @gnufoo/canaad npm package (0.5.1). Built from canaad-wasm via wasm-pack, with a hand-maintained JS wrapper layer.

versioning: @gnufoo/canaad (npm) and the rust crates are versioned independently — npm at 0.5.x, rust at 0.3.x.

npm install @gnufoo/canaad@^0.5

Main export — @gnufoo/canaad

The default entry point re-exports the WASM bindings directly.

canonicalize(json: string): Uint8Array

Parses and canonicalizes a JSON string to deterministic bytes per RFC 8785.

import { canonicalize } from '@gnufoo/canaad';
const bytes = canonicalize('{"v":1,"tenant":"acme","resource":"/doc/123","purpose":"encrypt"}');

Throws JsError on invalid JSON or AAD constraint violation.

canonicalizeString(json: string): string

Same as canonicalize, but returns the canonical form as a UTF-8 string.

import { canonicalizeString } from '@gnufoo/canaad';
const str = canonicalizeString('{"v":1,"tenant":"acme","resource":"/doc/123","purpose":"encrypt"}');

validate(json: string): boolean

Validates a JSON string against the AAD specification. Returns true or falseno error detail. Use canonicalize() or AadBuilder.build() when you need to distinguish the failure reason.

import { validate } from '@gnufoo/canaad';
if (!validate(untrustedInput)) { /* reject */ }

hash(json: string): Uint8Array

SHA-256 hash of the canonical JSON form.

import { hash } from '@gnufoo/canaad';
const digest = hash('{"v":1,"tenant":"acme","resource":"/doc/123","purpose":"encrypt"}');

Constants

Name Type Value Description
SPEC_VERSION number 1 Current AAD spec version
MAX_SAFE_INTEGER number 9007199254740991 2⁵³ − 1; ceiling for timestamp and integer extensions
MAX_SERIALIZED_BYTES number 16384 16 KiB cap on serialized AAD output

AadBuilder

Fluent builder for constructing AAD objects. Chain setters, then call build() or buildString().

import { AadBuilder } from '@gnufoo/canaad';

Constructor

new AadBuilder() — creates an empty builder.

Setters

All setters return this for chaining.

Method Argument Constraint
.tenant(value) string 1–256 UTF-8 bytes, no NUL
.resource(value) string 1–1024 UTF-8 bytes, no NUL
.purpose(value) string 1+ UTF-8 bytes, no NUL
.timestamp(ts) number Non-negative integer ≤ MAX_SAFE_INTEGER
.extensionString(key, value) string, string Key format: x_<app>_<field>
.extensionInt(key, value) string, number Key format: x_<app>_<field>; value: non-negative integer ≤ MAX_SAFE_INTEGER

Validation is deferred. Setters store raw values. Constraints (NaN, Infinity, negative, fractional, above MAX_SAFE_INTEGER, field length limits) are checked when build() or buildString() is called.

Terminal methods

Method Returns Description
.build() Uint8Array Validates all fields, produces canonical AAD bytes
.buildString() string Validates all fields, produces canonical AAD as UTF-8 string

Both throw JsError on validation failure. Required fields: tenant, resource, purpose.


Subpath exports

@gnufoo/canaad/init

Manual WASM initialization. Call initWasm() once before using any WASM function.

import { initWasm, isInitialized } from '@gnufoo/canaad/init';
Function Signature Description
initWasm (wasmModule?: WebAssembly.Module) => Promise<void> Initialize WASM. Pass a precompiled module in Workers; omit in browser. Safe to call multiple times — subsequent calls are no-ops.
isInitialized () => boolean Returns true after initWasm() has completed.

@gnufoo/canaad/meta

Package metadata and Zod schemas for structured tool integration.

import { meta, inputSchema, outputSchema } from '@gnufoo/canaad/meta';

meta object:

Field Value
id "canaad"
name "canaad"
description "canonicalize JSON for AAD (Additional Authenticated Data) per RFC 8785"
category "crypto"
executionType "hybrid"

inputSchema — Zod discriminated union on action. Four actions:

  • canonicalize{ action, input, outputFormat?: 'bytes' | 'string' }
  • validate{ action, input }
  • hash{ action, input, outputFormat?: 'hex' | 'base64' }
  • build{ action, tenant, resource, purpose, timestamp?, extensions?, outputFormat?: 'bytes' | 'string' }

outputSchema — Zod discriminated union matching each action's response shape.

@gnufoo/canaad/tool

Complete tool integration: merges metadata, WASM lifecycle, and an action dispatcher.

import { toolDefinition } from '@gnufoo/canaad/tool';

toolDefinition exposes:

  • All fields from meta
  • initWasm() and isInitialized() from init
  • execute(rawInput) — validates input against inputSchema, dispatches to the matching WASM function, returns a typed result matching outputSchema
await toolDefinition.initWasm();
const result = await toolDefinition.execute({
  action: 'build',
  tenant: 'acme',
  resource: '/doc/123',
  purpose: 'encrypt',
  outputFormat: 'string',
});
// { action: 'build', output: '{...}', outputFormat: 'string' }

execute() throws WasmNotInitializedError if called before initWasm() completes.


Errors

WasmNotInitializedError

Imported from @gnufoo/canaad/errors (also re-exported from @gnufoo/canaad/tool).

import { WasmNotInitializedError } from '@gnufoo/canaad/errors';
Property Type Value
.name string "WasmNotInitializedError"
.kind string "WasmNotInitializedError" — discriminant for branded error handling
.message string "WASM not initialized. Call initWasm() first."
try {
  canonicalize(json);
} catch (e) {
  if (e instanceof WasmNotInitializedError) {
    await initWasm();
    // retry
  }
}