docs: update README and docs for v0.6.0 architecture and deployment, preserve current server/shared/wasm updates

This commit is contained in:
thakares committed 2026-05-29 21:27:11 +05:30
1 parent 6067746898
commit 2b8afd54e0
27 files changed
+1413 -2567

No files matched your search

+70 -238
View File
@@ -1,301 +1,133 @@
# ChronoSeal — WASM Build Guide
# ChronoSeal WASM Build Guide
## Overview
ChronoSeal uses a Rust-based WASM runtime to power browser-side attestation logic, signing, hash chaining, VM execution, and mutation commitment preview.
The client-side cryptographic core of ChronoSeal is written in Rust and
compiled to WebAssembly (WASM). The JavaScript frontend (`heartbeat.js`)
imports functions from this WASM module to generate keypairs, sign heartbeat
payloads, compute hash chain links, and execute the stack machine program.
## Why WASM
The import line in `heartbeat.js`:
The WASM runtime provides a deterministic, sandboxed environment for the following tasks:
```js
import init, { generate_keypair, sign_message, compute_next_hash, run_program }
from './pkg/antibot_wasm.js';
```
* generate Ed25519 keypairs in-browser
* sign canonical heartbeat payloads
* execute randomized VM opcode programs
* compute Blake3 hash chain progression
* preview and commit synthetic gene mutations
`./pkg/antibot_wasm.js` is a **generated file**. It does not exist in the
repository and must be produced by building the `wasm/` crate before running
the server.
This enables server/client parity and prevents the private key from leaving the browser runtime.
---
## Build Requirements
## How the WASM Module is Built
The tool that compiles Rust to WASM and generates the JavaScript glue is
[`wasm-pack`](https://rustwasm.github.io/wasm-pack/).
When you run:
```bash
wasm-pack build wasm --target web --release
```
wasm-pack does the following in sequence:
1. Compiles `wasm/src/lib.rs` (and its submodules) to a `.wasm` binary using
the `wasm32-unknown-unknown` target.
2. Runs `wasm-bindgen` to inspect every `#[wasm_bindgen]`-annotated function
and struct and generate a JavaScript wrapper for each one.
3. Optionally runs `wasm-opt` (from Binaryen) to size-optimise the binary.
4. Writes all output to `wasm/pkg/`.
---
## Output: `wasm/pkg/`
After a successful build, `wasm/pkg/` contains:
```
wasm/pkg/
├── antibot_wasm.js ← ES module; the file heartbeat.js imports
├── antibot_wasm_bg.wasm ← compiled WASM binary (~300–800 KB release)
├── antibot_wasm_bg.js ← internal memory bridge (do not import directly)
├── antibot_wasm.d.ts ← TypeScript type declarations
├── antibot_wasm_bg.d.ts ← TypeScript declarations for the bg module
└── package.json
```
### `antibot_wasm.js`
This is the public entry point. It contains:
- An `init()` function that fetches and instantiates the `.wasm` binary.
- One JavaScript wrapper function for each `#[wasm_bindgen]` export in
`wasm/src/`:
| Rust export | JS wrapper | Description |
|---|---|---|
| `generate_keypair()` | `generate_keypair()` | Generate Ed25519 keypair; return hex public key |
| `get_public_key()` | `get_public_key()` | Return hex public key, or `""` if not initialised |
| `sign_message(msg)` | `sign_message(msg)` | Sign string; return hex signature, or `""` if not initialised |
| `compute_next_hash(prev, ts, entropy, stack, salt)` | `compute_next_hash(...)` | Compute next Blake3 chain hash |
| `run_program(b64)` | `run_program(b64)` | Execute base64 VM program; return `{ stack, ip }` |
### `antibot_wasm_bg.wasm`
The compiled binary. The `.bg` suffix means "background" — this is the raw
WASM that `antibot_wasm.js` loads internally. You should not reference this
file directly in your HTML.
---
## Step-by-Step Build
### 1. Install the Rust WASM target
Install the Rust WASM target and `wasm-pack`:
```bash
rustup target add wasm32-unknown-unknown
```
This is a one-time step. Without it, the Rust compiler cannot produce WASM
output.
### 2. Install wasm-pack
```bash
cargo install wasm-pack
```
Or via the installer script:
```bash
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
```
Verify:
```bash
wasm-pack --version
# wasm-pack 0.13.x
```
### 3. Build the WASM module
## Build the WASM Module
From the project root:
From the repository root:
```bash
wasm-pack build wasm --target web --release
```
`--target web` produces an ES module (`import`/`export` syntax) suitable for
use directly in a browser without a bundler. Other targets (`bundler`,
`nodejs`, `no-modules`) produce different output formats and are not
compatible with the ChronoSeal frontend as written.
`--release` enables Rust's release optimisations (inlining, dead code
elimination, size reduction). Omit it during development for faster builds
and better panic messages.
### 4. Move the output to the frontend
```bash
rm -rf frontend/pkg
mv wasm/pkg frontend/pkg
```
The frontend expects the WASM module at `frontend/pkg/antibot_wasm.js`
because `heartbeat.js` imports from `./pkg/antibot_wasm.js` relative to
the `frontend/` directory, which is where the server's static file handler
is rooted.
`--target web` produces an ES module compatible with the existing frontend JavaScript.
---
`--release` enables optimizations for runtime performance and size.
## Using the Build Script
## Output
The convenience script at `scripts/build.sh` performs all steps in order:
After a successful build, `frontend/pkg/` contains:
```bash
bash scripts/build.sh
```
* `antibot_wasm.js`
* `antibot_wasm_bg.wasm`
* `antibot_wasm_bg.js`
* `antibot_wasm.d.ts`
* `antibot_wasm_bg.d.ts`
* `package.json`
This builds the WASM module, moves it to `frontend/pkg/`, and then builds
the server binary. Run this for a clean full build before deployment.
The frontend expects the WASM package under `frontend/pkg/`.
For development iteration where you are only changing Rust WASM code:
## Runtime Exports
```bash
wasm-pack build wasm --target web # (omit --release for speed)
rm -rf frontend/pkg && mv wasm/pkg frontend/pkg
```
The WASM module exports the following functions:
For development where you are only changing server code:
* `generate_keypair()` — generate a new Ed25519 keypair and return public key hex
* `get_public_key()` — return the current public key hex
* `sign_message(msg)` — sign a UTF-8 payload and return the hex signature
* `compute_next_hash(prev, ts, entropy, stack, salt)` — compute the next Blake3 chain hash
* `run_program(b64)` — execute a base64 VM program and return stack state
* `init_gene_state(gene_size)` — initialise the synthetic gene buffer
* `preview_gene_commitment(order_b64)` — preview the next gene commitment from a mutation order
* `commit_gene_preview()` — commit the previewed mutation after successful heartbeat
* `discard_gene_preview()` — discard the previewed mutation after rejection or error
* `current_gene_commitment()` — return the current committed gene commitment
```bash
cargo build -p server
```
## Browser Integration
---
## How `heartbeat.js` Loads the Module
`heartbeat.js` uses a standard ES module dynamic import pattern:
The frontend imports the generated module like this:
```js
import init, { generate_keypair, sign_message, compute_next_hash, run_program }
from './pkg/antibot_wasm.js';
export async function initHeartbeat() {
// 1. Fetch and instantiate the .wasm binary
await init();
// 2. Generate keypair — private key stored in WASM memory only
const pubKeyHex = generate_keypair();
// 3. Send public key to server, receive session_id and chain seed
// ...
}
import init, {
generate_keypair,
sign_message,
compute_next_hash,
run_program,
init_gene_state,
preview_gene_commitment,
commit_gene_preview,
discard_gene_preview,
current_gene_commitment
} from './pkg/antibot_wasm.js';
```
`init()` is the default export from `antibot_wasm.js`. It fetches
`antibot_wasm_bg.wasm` (from the same `pkg/` directory) via `fetch()`,
compiles it in the browser's WASM engine, and links it to the JS glue
layer. After `await init()` returns, all the named exports
(`generate_keypair`, `sign_message`, etc.) are ready to call.
`await init()` must be called before invoking any other exported function.
The `init()` call must complete before any other WASM function is called.
Calling `sign_message()` or `compute_next_hash()` before `await init()`
returns will produce an empty string (the module is not yet instantiated).
## Deployment Note
---
## Serving the WASM Binary
Browsers require WASM files to be served with the correct MIME type:
The `.wasm` binary must be served with the correct MIME type:
```
Content-Type: application/wasm
```
Most web servers set this automatically for `.wasm` files. If you see the
error:
The built-in Axum static file handler already sets the appropriate MIME type for `.wasm` files.
```
WebAssembly.instantiate(): Response has unsupported MIME type
```
## Build Script
Add the MIME type to your server configuration:
**nginx:**
```nginx
types {
application/wasm wasm;
}
```
**Apache `.htaccess`:**
```apache
AddType application/wasm .wasm
```
The Axum `ServeDir` handler used by ChronoSeal's built-in static server
sets the correct MIME type automatically via `tower-http`.
---
## What Is Not in the Repository
| Path | Why excluded |
|---|---|
| `wasm/pkg/` | Generated build output — changes on every build |
| `frontend/pkg/` | Same generated output, moved to serve location |
| `target/` | Standard Rust build artefacts |
Both `wasm/pkg/` and `frontend/pkg/` are listed in `.gitignore`. Committing
them would bloat the repository (the `.wasm` binary alone is 300–800 KB),
create noisy diffs on every rebuild, and give a false impression that the
WASM module is pre-built and ready to use without a build step.
---
## Troubleshooting
### `wasm32-unknown-unknown` target not found
```
error[E0463]: can't find crate for `std`
```
Fix:
Use the convenience script:
```bash
rustup target add wasm32-unknown-unknown
bash scripts/build.sh
```
### `wasm-pack` not found
This builds the WASM package, moves it into `frontend/pkg/`, and builds the server binary.
## Recommended Development Flow
* For WASM-only changes:
```bash
cargo install wasm-pack
wasm-pack build wasm --target web
rm -rf frontend/pkg
mv wasm/pkg frontend/pkg
```
### `wasm-opt` not found (warning, not an error)
wasm-pack prints a warning if `wasm-opt` is not installed. The build still
succeeds; the binary is just not size-optimised.
* For server-only changes:
```bash
# On Debian/Ubuntu/Arch
sudo apt install binaryen # Debian/Ubuntu
sudo pacman -S binaryen # Arch
cargo build -p server
```
### `antibot_wasm_bg.wasm` fetch fails (404)
## Notes
The `.wasm` file is not being served from `frontend/pkg/`. Verify:
```bash
ls /mnt/Programs/ChronoSeal/frontend/pkg/
# Should list: antibot_wasm.js antibot_wasm_bg.wasm ...
```
If the directory is empty or missing, re-run the build steps above.
### MIME type error in browser
See the "Serving the WASM Binary" section above.
### `sign_message` or `generate_keypair` returns empty string
The WASM keypair has not been initialised. Ensure `await init()` and
`generate_keypair()` are called (and awaited) before any other WASM
function. Check the browser console for any errors during `init()`.
Generated files in `wasm/pkg/` and `frontend/pkg/` are not tracked in source control.
They are build artifacts and should be regenerated as part of the release workflow.