Skip to content

development

xero edited this page May 30, 2026 · 1 revision
logo

Development

Developer workflow for leviathan-crypto: building, testing, linting. For the internal build pipeline architecture see architecture.md. For the test corpus structure see test-suite.md.

Table of Contents


First-time setup

Clone the repository and install dependencies. Bun is the only required toolchain.

bun i

For end-to-end tests you also need Playwright and its browser engines. Run this once per machine, after bun i. It installs Playwright globally and downloads the Chromium, Firefox, and WebKit browser binaries Playwright drives.

bun run test e2e:install

The e2e:install step mirrors the CI Docker image, so a local install matches what the test suite runs against in CI.


The full check

bun check

bun check is the primary verification command. It performs a full clean build, then runs lint, unit tests, and end-to-end tests in parallel as separate processes. Each child task streams its output with a colored prefix tag, and the run ends with a per-task summary:

  ✓ lint    8.4s
  ✓ unit  142.7s
  ✓ e2e   213.1s

  total 213.4s

Exit code reflects the worst child. A failing task does not stop its siblings, so a single run reports every problem at once. Parallelization drops the average run time from ~5min to ~1min.


Targeted commands

For the common case where you do not need to rerun the full suite, use the targeted shorthands. Each one performs only the build steps it requires, then runs its tool.

bun bake. Full build only. Walks the build dependency graph defined in scripts/lib/build-graph.ts and produces build/, dist/, the embedded blobs, and the root CLAUDE.md. Useful before publishing locally or testing a built bundle in a downstream project.

bun fix. ESLint with --fix applied. Run this before considering any work complete; lint errors fail CICD tests.

bun unit <file>. Run a single unit test. Builds the asm, embed, embed-workers, and ts targets first. Forwards any extra arguments to vitest.

bun unit test/unit/aes/aes_kat.test.ts
bun unit test/unit/aes/                       # all files under one directory

bun e2e <file>. Run a single e2e spec. Builds everything first. Forwards any extra arguments to playwright.

bun e2e test/e2e/seal.spec.ts
bun e2e test/e2e/seal.spec.ts --project=chromium

bun run test unit:group <name>. Run one CI test group locally. Builds the group's declared prerequisites, then runs the file list from scripts/lib/test-groups.ts. Group names match the .github/workflows/unit-*.yml suffixes: core, serpent, chacha20, stream, mlkem, hashing, montecarlo-cbc, montecarlo-ecb, nessie, ratchet, aes, aes-siv, aes-mct, mldsa.

bun run test unit:group aes

bun pin. Re-pin every GitHub Action reference in .github/workflows/*.yml to a commit SHA. Run after any workflow edit, before committing.


Build targets

bun bake runs every target. When you only changed part of the codebase and want a faster rebuild, run a single target with bun bake <target>.

Target Inputs Outputs When to use
asm src/asm/*/index.ts build/*.wasm Edits to AssemblyScript sources
embed build/*.wasm src/ts/embedded/<module>.ts, src/ts/cte-wasm.ts After asm rebuilds
embed-workers src/ts/<cipher>/pool-worker.ts src/ts/embedded/<cipher>-pool-worker.ts Edits to pool worker sources
ts src/ts/** dist/ Edits to TypeScript sources without an asm rebuild
wasm-copy build/*.wasm dist/*.wasm URL-loaded consumer testing
claude-md docs/CLAUDE_consumer.md CLAUDE.md at repo root After consumer-doc edits

Each target cleans its own outputs before writing. Force is the only mode; there is no staleness check and no --force flag.


Output locations

build/                 raw .wasm + asc-emitted .js/.d.ts (gitignored)
dist/                  published npm package contents (gitignored)
src/ts/embedded/       generated TS thunks: gz+b64 blobs + pool-worker IIFE strings (gitignored)
src/ts/cte-wasm.ts     generated raw byte array for the cte module (gitignored)
CLAUDE.md              copy of docs/CLAUDE_consumer.md, ships in the npm tarball

Every generated path is gitignored. Treat them as build artifacts. Never hand-edit anything under src/ts/embedded/ or src/ts/cte-wasm.ts; the next bun bake overwrites them.


Troubleshooting

Stale output after a branch switch or a partial run. Nuke the build outputs and rebuild from scratch.

rm -rf build dist src/ts/embedded src/ts/cte-wasm.ts CLAUDE.md
bun bake

Narrowing a failure to one test group. When bun check shows a unit failure, run that group alone to iterate without the e2e overhead.

bun run test unit:group aes

A single test fails inconsistently. Run it directly with the verbose reporter that bun unit passes by default.

bun unit test/unit/stream/seal.test.ts

ESLint or TypeScript complains after a dependency bump. bun fix handles the autofixable subset. Anything left is a real issue.


Cross-References

Document Description
index Project documentation index
architecture Repository structure, build and CI, WASM modules, public API, test suite, and security posture
test-suite.md Test corpus structure, vector provenance, and gate discipline
examples.md Worked examples for every primitive
exports.md Complete export reference
init.md init() API, WasmSource, subpath imports, tree-shaking
audits.md Per-primitive audit index
Agent Instructions Contract for AI-assisted development on this repository

Leviathan-Crypto Wiki

Leviathan logo

Getting Started

Authenticated Encryption

Digital Signatures

Ciphers

  • Serpent-256 TypeScript | WASM
    • Serpent, SerpentCtr, SerpentCbc, SerpentGenerator
  • ChaCha20 TypeScript | WASM
    • ChaCha20, Poly1305, ChaCha20Poly1305, XChaCha20Poly1305, ChaCha20Generator
  • AES TypeScript | WASM
    • AES, AESCbc, AESCtr, AESGCM, AESGCMSIV, AESGenerator

Signature Primitives

  • ML-DSA TypeScript | WASM
    • pure (FIPS 204): MlDsa44, MlDsa65, MlDsa87
    • pure-mode suites: MlDsa44Suite, MlDsa65Suite, MlDsa87Suite
    • prehash suites: MlDsa44PreHashSuite, MlDsa65PreHashSuite, MlDsa87PreHashSuite
  • SLH-DSA TypeScript | WASM
    • pure (FIPS 205): SlhDsa128f, SlhDsa192f, SlhDsa256f
    • pure-mode suites: SlhDsa128fSuite, SlhDsa192fSuite, SlhDsa256fSuite
    • prehash suites: SlhDsa128fPreHashSuite, SlhDsa192fPreHashSuite, SlhDsa256fPreHashSuite
  • Ed25519 TypeScript | WASM
    • Ed25519 (pure + Ed25519ph), Ed25519Suite, Ed25519PreHashSuite
  • ECDSA-P256 TypeScript | WASM
    • EcdsaP256 (hedged + RFC 6979), EcdsaP256Suite
    • DER codec: ecdsaSignatureToDer, ecdsaSignatureFromDer, encodeEcPrivateKey, decodeEcPrivateKey, pointDecompress
  • Hybrid composites PQ-only | Classical+PQ
    • PQ-only: MlDsa44SlhDsa128fSuite, MlDsa65SlhDsa192fSuite, MlDsa87SlhDsa256fSuite
    • Classical+PQ: MlDsa44Ed25519Suite, MlDsa65Ed25519Suite, MlDsa44EcdsaP256Suite, MlDsa65EcdsaP256Suite

Key Agreement

Post-Quantum

  • ML-KEM TypeScript | WASM
    • MlKem512, MlKem768, MlKem1024
  • Ratchet (SPQR)
    • KDFChain, ratchetInit, kemRatchetEncap, kemRatchetDecap, RatchetKeypair, SkippedKeyStore

Hashing

  • Hashing overview
  • SHA-2 TypeScript | WASM
    • SHA256, SHA384, SHA512, SHA224, SHA512_224, SHA512_256
    • HMAC_SHA256, HMAC_SHA384, HMAC_SHA512, HKDF_SHA256, HKDF_SHA512
  • SHA-3 TypeScript | WASM
    • SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE128, SHAKE256
  • BLAKE3 TypeScript | WASM
    • BLAKE3, BLAKE3Stream, BLAKE3KeyedHash, BLAKE3KeyedHashStream
    • BLAKE3DeriveKey, BLAKE3DeriveKeyStream, BLAKE3OutputReader, BLAKE3Hash
  • KMAC
    • CSHAKE128, CSHAKE256, KMAC128, KMAC256, KMACXOF128, KMACXOF256

Transparency Log

  • Merkle
    • MerkleVerifier, MerkleLog
    • SignedLog, Sha256Tree, Blake3Tree, MemoryStorage

Utilities

  • Fortuna CSPRNG
    • Fortuna, SerpentGenerator, ChaCha20Generator, AESGenerator, SHA256Hash, SHA3_256Hash, BLAKE3Hash
  • Utils TypeScript | WASM
    • constantTimeEqual, randomBytes, wipe, encoding helpers
  • TypeScript interfaces
    • Hash, KeyedHash, Blockcipher, Streamcipher, AEAD, Generator, HashFn

Project

Reference

Clone this wiki locally