Refactor attestation engine and synchronize project documentation

- Refine session and storage lifecycle handling
- Improve VM extension architecture across server, shared, and WASM runtimes
- Enhance synthetic gene mutation engine integration and parity guarantees
- Align deterministic state progression between server and browser execution paths
- Update configuration examples and deployment guidance
- Expand architecture, API, threat model, privacy, and WASM build documentation
- Refresh README with comprehensive project overview, operational workflows,
  browser integration details, storage backend documentation, and security model
- Document v0.6.0 refactoring outcomes and design rationale
- Improve consistency across documentation, configuration, and implementation

This commit consolidates the v0.6.0 architectural refactoring effort,
strengthening deterministic browser/server parity while improving
maintainability, operational clarity, and project documentation.
This commit is contained in:
thakares committed 2026-05-29 21:55:08 +05:30
1 parent 2b8afd54e0
commit 0ed3cb444d
15 files changed
+2357 -797

No files matched your search

+668 -146
View File
@@ -9,15 +9,15 @@
</p>
<p align="center">
Privacy-first • Deterministic WASM parity • Silent rejection • Low overhead
Privacy-first | Deterministic WASM parity | Silent rejection | Low overhead
</p>
<p align="center">
<a href="https://github.com/thakares/chronoseal-rs/blob/main/LICENSE">
<img src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg" alt="License: MIT OR Apache-2.0">
</a>
<img src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg" alt="License: MIT OR Apache-2.0">
</a>
<a href="https://github.com/thakares/chronoseal-rs">
<img src="https://img.shields.io/badge/rust-stable%20%E2%89%A5%201.87-orange.svg" alt="Rust stable ≥ 1.87">
<img src="https://img.shields.io/badge/rust-stable%20%E2%89%A5%201.87-orange.svg" alt="Rust stable >= 1.87">
</a>
<a href="https://github.com/thakares/chronoseal-rs/blob/main/docs/REFRACTORING-v0.6.0.md">
<img src="https://img.shields.io/badge/version-v0.6.0-green.svg" alt="v0.6.0">
@@ -27,200 +27,722 @@
---
ChronoSeal is a mature Unix-native cryptographic attestation daemon for browser session continuity and anti-automation defense.
ChronoSeal is a Linux-native cryptographic attestation service for browser session continuity and anti-automation defense. It runs as a small daemon, serves a browser WASM runtime, and validates signed heartbeat requests through deterministic server/client state progression.
It provides a low-overhead, privacy-respecting proof-of-runtime system built around a deterministic **Synthetic Gene Mutation Engine** and a silent, replay-resistant heartbeat protocol.
The core idea is simple: a real browser session should be able to keep advancing a private cryptographic state, a hash chain, and a deterministic synthetic gene mutation chain. Basic HTTP clients, stale replay attempts, and incomplete automation should fail without receiving a useful failure reason.
v0.6.0 introduces the core innovation: a deterministic synthetic gene mutation chain with server/WASM parity, stronger liveness guarantees, and a domain-separated mutation commitment handshake.
ChronoSeal is a cost-raising attestation layer. It is not a CAPTCHA replacement, identity provider, fingerprinting product, or perfect bot blocker.
---
## Contents
## What ChronoSeal Provides
- [Features](#features)
- [How It Works](#how-it-works)
- [Repository Layout](#repository-layout)
- [Quick Start](#quick-start)
- [Build From Source](#build-from-source)
- [Run Locally](#run-locally)
- [Install as a Service](#install-as-a-service)
- [Docker](#docker)
- [CLI Reference](#cli-reference)
- [Configuration](#configuration)
- [HTTP API](#http-api)
- [Browser Integration](#browser-integration)
- [Storage Backends](#storage-backends)
- [Operations](#operations)
- [Security Model](#security-model)
- [Development](#development)
- [Troubleshooting](#troubleshooting)
- [Further Reading](#further-reading)
- [License](#license)
* Native Linux daemon with hardened `systemd` integration
* Deterministic mutation engine running in both server Rust and client WASM
* Silent rejection semantics for attacker resilience
* Multi-backend storage: `sqlite-in-memory`, `sqlite-disk`, and `valkey`
* CLI-first operation with rich subcommands
* Structured logging, PID file management, graceful shutdown
* Prometheus-compatible metrics and runtime statistics
* Lightweight browser runtime with WASM-based attestation
* Privacy-first design with ephemeral session state and no persistent tracking
## Features
---
- Native Unix daemon with `systemd` service support.
- Axum-based HTTP service exposing `/init`, `/hb`, `/health`, `/metrics`, and `/stats`.
- Rust/WASM browser runtime for key generation, signing, VM execution, and mutation preview.
- Deterministic Synthetic Gene Mutation Engine shared by the server and WASM crates.
- Ed25519 signatures over canonical heartbeat payloads.
- Blake3 hash chain continuity across accepted heartbeats.
- Silent rejection semantics: invalid heartbeats still return `{"status":"ok"}`.
- Configurable behavioral trust checks for mouse movement, pauses, timing, and browser signals.
- Runtime storage abstraction with `sqlite-in-memory`, `sqlite-in-disk`, and `valkey` modes.
- CLI-first lifecycle, status, health, metrics, stats, config validation, key generation, and shell completions.
- Privacy-oriented design based on ephemeral session state rather than long-term identity tracking.
## Why ChronoSeal
## How It Works
ChronoSeal raises the operational cost of automation by combining:
ChronoSeal creates a short-lived browser attestation session and advances it through signed heartbeats.
* cryptographic session continuity
* deterministic VM execution
* behavioral entropy validation
* mutation commitment parity
* silent, ambiguous rejection behavior
1. The browser loads the generated WASM package from `frontend/pkg`.
2. The WASM runtime generates an Ed25519 keypair and returns the public key to JavaScript.
3. The browser calls `POST /init` with the public key.
4. The server creates a session and returns:
- `session_id`
- initial salt
- initial hash chain head
- VM opcode program
- gene size
- mutation step
- mutation order
- heartbeat timing bounds
5. For each heartbeat, the browser:
- executes the VM opcode program
- collects entropy and browser signal data
- previews the next synthetic gene commitment in WASM
- signs the canonical heartbeat payload
- posts the request to `POST /hb`
6. The server validates:
- session existence and expiration
- rate limit
- timestamp drift
- Ed25519 signature
- hash chain continuity
- behavioral trust checks
- mutation step
- gene commitment parity
7. If the heartbeat is accepted, the server advances session state and returns the next salt and mutation order.
8. If the heartbeat is rejected, the server returns only `{"status":"ok"}`.
This is not a fingerprinting or surveillance platform. ChronoSeal is designed to make automation expensive, not to collect user identities.
The silent failure model deliberately avoids exposing which validation failed.
---
## Repository Layout
```text
.
├── Cargo.toml # Rust workspace
├── server/ # chronoseal daemon and CLI
├── shared/ # shared protocol, gene model, mutation engine
├── wasm/ # WASM runtime crate
├── frontend/ # static browser integration files
├── docs/ # architecture, API, deployment, threat model
├── scripts/ # build, install, release, dev helpers
├── chronoseal.service # systemd unit
├── Dockerfile # container image
└── docker-compose.yml # local container orchestration
```
Workspace members:
- `chronoseal-server`: daemon binary crate. Binary name: `chronoseal`.
- `shared`: common cryptographic and mutation logic used by server and WASM.
- `chronoseal-wasm`: browser runtime compiled with `wasm-pack`.
## Quick Start
### Install
For a full native install:
```bash
sudo bash scripts/install.sh
```
### Verify status
Check the daemon:
```bash
chronoseal status --format json
```
### Health probe
```bash
chronoseal health
```
### View metrics
```bash
chronoseal metrics
```
### Follow logs
```bash
sudo journalctl -u chronoseal -f
```
---
For local development without installing:
## CLI Overview
```bash
bash scripts/build.sh
cargo run -p chronoseal-server --bin chronoseal -- run \
--bind 127.0.0.1:3000 \
--frontend-dir frontend
```
Then open:
```text
http://127.0.0.1:3000
```
## Build From Source
### Requirements
| Tool | Minimum | Purpose |
|---|---:|---|
| Rust | 1.87 stable | Build server, shared crate, and tests |
| wasm-pack | 0.13 | Build browser WASM package |
| wasm32 target | current stable | WASM compilation target |
| systemd | 248+ | Optional native service management |
| Docker | 24.x | Optional container workflow |
| Docker Compose | 2.x | Optional local orchestration |
Install the WASM target and `wasm-pack`:
```bash
rustup target add wasm32-unknown-unknown
cargo install wasm-pack
```
Build everything needed for the browser and server:
```bash
bash scripts/build.sh
```
That script:
1. Builds `wasm/` with `wasm-pack build --target web --release`.
2. Replaces `frontend/pkg` with the generated WASM package.
3. Builds the `chronoseal` release binary.
Manual build:
```bash
wasm-pack build wasm --target web --release
rm -rf frontend/pkg
mv wasm/pkg frontend/pkg
cargo build -p chronoseal-server --bin chronoseal --release
```
The binary is written to:
```text
target/release/chronoseal
```
## Run Locally
Run the daemon directly from Cargo:
```bash
cargo run -p chronoseal-server --bin chronoseal -- run \
--bind 127.0.0.1:3000 \
--frontend-dir frontend
```
Probe it:
```bash
curl http://127.0.0.1:3000/health
curl http://127.0.0.1:3000/stats
curl http://127.0.0.1:3000/metrics
```
Use the CLI wrappers:
```bash
cargo run -p chronoseal-server --bin chronoseal -- status --bind 127.0.0.1:3000
cargo run -p chronoseal-server --bin chronoseal -- health --bind 127.0.0.1:3000
cargo run -p chronoseal-server --bin chronoseal -- stats --bind 127.0.0.1:3000 --format json
```
## Install as a Service
The installer builds the project, installs the binary, copies frontend assets, installs the `systemd` unit, and starts the service.
```bash
sudo bash scripts/install.sh
```
Installed paths:
| Path | Purpose |
|---|---|
| `/usr/local/bin/chronoseal` | daemon and CLI binary |
| `/opt/chronoseal/frontend` | static frontend assets copied by installer |
| `/etc/systemd/system/chronoseal.service` | service unit |
| `/run/chronoseal.pid` | default PID file |
Service commands:
```bash
sudo systemctl status chronoseal
sudo systemctl restart chronoseal
sudo systemctl disable --now chronoseal
sudo journalctl -u chronoseal -f
```
## Docker
Build and run with Compose:
```bash
docker compose up -d --build
```
The provided container exposes port `3000`.
```bash
curl http://127.0.0.1:3000/health
```
Important: the Dockerfile copies `frontend/` from the working tree. Build the WASM package into `frontend/pkg` before building the container if you need the browser runtime inside the image:
```bash
bash scripts/build.sh
docker compose up -d --build
```
## CLI Reference
Run:
```bash
chronoseal --help
```
### Available commands
Global options:
| Command | Description |
| ------------ | ------------------------------------------ |
| `run` | Run the ChronoSeal daemon |
| `status` | Report daemon status |
| `health` | Perform daemon health probe |
| `config` | Validate and print effective configuration |
| `generate` | Generate operational material |
| `db-type` | List database backend support status |
| `metrics` | Output Prometheus metrics |
| `stats` | Print runtime statistics |
| `completion` | Generate shell completions |
| `version` | Print version/build information |
| Option | Environment | Description |
|---|---|---|
| `--config <path>` | `CHRONOSEAL_CONFIG` | Explicit TOML config path |
| `--format <text|json|yaml>` | - | Output format for machine-readable commands |
| `--output <text|json|yaml>` | - | Alias for `--format` |
| `--log <filter>` | `CHRONOSEAL_LOG` | Tracing filter, for example `info` or `chronoseal=debug` |
---
Commands:
## Example
| Command | Description |
|---|---|
| `chronoseal run` | Run the daemon |
| `chronoseal status` | Check configured daemon reachability and PID state |
| `chronoseal health` | Perform an HTTP health probe |
| `chronoseal config check` | Validate and print effective configuration |
| `chronoseal generate keypair` | Generate an Ed25519 keypair |
| `chronoseal version` | Print version/build information |
| `chronoseal db-type` | List database backend support status |
| `chronoseal metrics` | Fetch Prometheus metrics from the running daemon |
| `chronoseal stats` | Fetch service statistics from the running daemon |
| `chronoseal completion <shell>` | Generate shell completions |
Examples:
```bash
chronoseal run --bind 127.0.0.1:3000 --frontend-dir frontend
chronoseal run --db-type sqlite-in-memory
chronoseal status --format json
chronoseal health --config /etc/chronoseal/config.toml
chronoseal config check --output yaml
chronoseal generate keypair --format json
chronoseal completion bash > chronoseal.bash
```
## Configuration
Configuration precedence:
1. CLI flags
2. `CHRONOSEAL_*` environment variables
3. TOML config file
4. built-in defaults
Default config discovery:
1. path from `CHRONOSEAL_CONFIG`, if it exists
2. `/etc/chronoseal/config.toml`
3. `$XDG_CONFIG_HOME/chronoseal/config.toml`
4. `~/.config/chronoseal/config.toml`
Example:
```toml
bind = "0.0.0.0:3000"
db_type = "sqlite-in-memory"
pid_file = "/run/chronoseal.pid"
db_path = "/var/lib/chronoseal/chronoseal.sqlite"
frontend_dir = "/usr/share/chronoseal/frontend"
log_file = "/var/log/chronoseal/chronoseal.jsonl"
heartbeat_min_interval_ms = 12000
heartbeat_max_interval_ms = 25000
expiration_minutes = 30
rate_limit_count = 5
rate_limit_window_secs = 10
max_timestamp_drift_ms = 30000
min_mouse_total_dist = 10.0
max_mouse_avg_speed = 2.0
min_pause_count = 1
require_mouse_activity = true
gene_size = 512
mutation_rounds = 4
```
Common environment variables:
| Variable | Description |
|---|---|
| `CHRONOSEAL_CONFIG` | Config file path |
| `CHRONOSEAL_BIND` | Bind address, for example `127.0.0.1:3000` |
| `CHRONOSEAL_DB_TYPE` | `sqlite-in-memory`, `sqlite-in-disk`, or `valkey` |
| `CHRONOSEAL_DB_PATH` | SQLite database path |
| `CHRONOSEAL_FRONTEND_DIR` | Static frontend directory served at `/` |
| `CHRONOSEAL_PID_FILE` | PID file path |
| `CHRONOSEAL_LOG` | Tracing filter |
| `CHRONOSEAL_LOG_FILE` | Optional JSON log file |
| `CHRONOSEAL_STATE_DIR` | Base state directory used for default `db_path` |
| `CHRONOSEAL_HEARTBEAT_MIN_INTERVAL_MS` | Minimum accepted heartbeat interval |
| `CHRONOSEAL_HEARTBEAT_MAX_INTERVAL_MS` | Maximum accepted heartbeat interval |
| `CHRONOSEAL_EXPIRATION_MINUTES` | Session lifetime |
| `CHRONOSEAL_RATE_LIMIT_COUNT` | Requests allowed in the rate-limit window |
| `CHRONOSEAL_RATE_LIMIT_WINDOW_SECS` | Rate-limit window length |
| `CHRONOSEAL_MAX_TIMESTAMP_DRIFT_MS` | Accepted client timestamp drift |
| `CHRONOSEAL_MIN_MOUSE_TOTAL_DIST` | Minimum mouse movement distance |
| `CHRONOSEAL_MAX_MOUSE_AVG_SPEED` | Maximum average mouse speed |
| `CHRONOSEAL_MIN_PAUSE_COUNT` | Minimum detected pause count |
| `CHRONOSEAL_REQUIRE_MOUSE_ACTIVITY` | Enable or disable mouse activity requirement |
| `CHRONOSEAL_GENE_SIZE` | Synthetic gene buffer size |
| `CHRONOSEAL_MUTATION_ROUNDS` | Mutation rounds per program |
Validate configuration:
```bash
chronoseal config check --format yaml
```
## HTTP API
ChronoSeal exposes a small HTTP surface:
| Method | Path | Purpose |
|---|---|---|
| `POST` | `/init` | Start a browser attestation session |
| `POST` | `/hb` | Submit a signed heartbeat |
| `GET` | `/health` | Health probe |
| `GET` | `/metrics` | Prometheus metrics |
| `GET` | `/stats` | Runtime statistics |
| `GET` | `/` | Static frontend files from `frontend_dir` |
### `POST /init`
Request:
```json
{
"public_key": "hex-encoded 32-byte Ed25519 verifying key"
}
```
Response:
```json
{
"session_id": "64-char hex string",
"salt": "32-char hex string",
"opcodes_b64": "base64-encoded VM program",
"initial_hash": "64-char hex string",
"expires_at": 1234567890123,
"heartbeat_min_interval_ms": 12000,
"heartbeat_max_interval_ms": 25000,
"gene_size": 512,
"mutation_step": 1,
"mutation_order_b64": "base64-encoded mutation program"
}
```
### `POST /hb`
Request:
```json
{
"session_id": "64-char hex",
"prev_hash": "64-char hex",
"timestamp": 1234567890123,
"entropy_data": {
"events": [
{ "x": 412.0, "y": 308.5, "t": 1234.567 }
]
},
"stack_state": {
"stack": [2971406957, 1234567890],
"ip": 42
},
"fingerprint": {
"aspectRatio": "1.7777777778",
"devicePixelRatio": 2,
"hardwareConcurrency": 8
},
"mutation_step": 1,
"gene_commitment": "64-char hex",
"signature": "128-char hex"
}
```
Accepted response:
```json
{
"status": "ok",
"next_salt": "32-char hex string",
"next_mutation_step": 2,
"next_mutation_order_b64": "base64-encoded mutation program"
}
```
Rejected response:
```json
{
"status": "ok"
}
```
Detailed API semantics are documented in [docs/API.md](docs/API.md).
## Browser Integration
The frontend imports the generated WASM module from `frontend/pkg`.
```js
import init, {
generate_keypair,
get_public_key,
sign_message,
compute_next_hash,
run_program,
init_gene_state,
preview_gene_commitment,
commit_gene_preview,
discard_gene_preview,
current_gene_commitment
} from './pkg/chronoseal_wasm.js';
```
Call `await init()` before invoking exported functions.
WASM exports:
| Function | Purpose |
|---|---|
| `generate_keypair()` | Generate a browser-local Ed25519 keypair and return public key hex |
| `get_public_key()` | Return current public key hex |
| `sign_message(msg)` | Sign a canonical UTF-8 payload and return signature hex |
| `compute_next_hash(prev, ts, entropy, stack, salt)` | Compute next Blake3 hash-chain value |
| `run_program(b64)` | Execute a base64 VM program and return stack state |
| `init_gene_state(gene_size)` | Initialize the synthetic gene buffer |
| `preview_gene_commitment(order_b64, session_id, mutation_step, rounds)` | Preview next gene commitment |
| `commit_gene_preview()` | Commit the previewed gene mutation after accepted heartbeat |
| `discard_gene_preview()` | Discard previewed mutation after rejection or error |
| `current_gene_commitment(session_id, mutation_step)` | Return current committed gene commitment |
String-returning WASM functions return an empty string on error. Boolean-returning functions indicate success or failure directly.
## Storage Backends
Set storage mode with `db_type` or `CHRONOSEAL_DB_TYPE`.
| Backend | Description |
|---|---|
| `sqlite-in-memory` | Default ephemeral session storage. State is lost on restart. |
| `sqlite-in-disk` | SQLite database persisted at `db_path`. |
| `valkey` | Valkey-compatible backend mode. |
For Valkey mode, the server reads `CHRONOSEAL_VALKEY_ADDR` and defaults to `127.0.0.1:6666` when it is not set. If the Valkey connection fails, the current implementation falls back to in-memory SQLite and logs a warning.
## Operations
### Health
```bash
chronoseal health
curl http://127.0.0.1:3000/health
```
### Status
```bash
chronoseal status --format json
```
```json
{
"running": true,
"healthy": true,
"bind": "0.0.0.0:3000",
"pid_file": "/run/chronoseal.pid",
"pid": 79459
### Metrics
```bash
chronoseal metrics
curl http://127.0.0.1:3000/metrics
```
### Stats
```bash
chronoseal stats --format json
curl http://127.0.0.1:3000/stats
```
### Logs
```bash
sudo journalctl -u chronoseal -f
```
Use `RUST_LOG=info` or `CHRONOSEAL_LOG=info` for normal production operation. Avoid debug logging in production because internal identifiers may appear in logs.
### Reverse Proxy
ChronoSeal should run behind TLS in production. Terminate HTTPS at a reverse proxy such as nginx, Caddy, HAProxy, or a cloud load balancer, then proxy to the local daemon.
Example nginx location:
```nginx
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
---
## Architecture Summary
ChronoSeal is composed of three primary runtime components:
* `shared/` — shared cryptographic primitives, hash chaining, gene model, and mutation engine used by both server and WASM
* `server/` — Axum-based Unix-native daemon, session lifecycle, storage, trust evaluation, and `POST /init` / `POST /hb` routes
* `wasm/` — browser runtime for key generation, signature creation, VM execution, and mutation preview/commit lifecycle
### Key innovations in v0.6.0
* Synthetic Gene Mutation Engine with deterministic, shared opcode semantics
* Server-side gene commitment validation on every heartbeat
* `mutation_step` and `mutation_order_b64` handshake in init and heartbeat responses
* `db_type` runtime backend selection with SQLite and Valkey support
---
## How ChronoSeal Works
ChronoSeal establishes continuity by chaining signed heartbeats between client and server.
### Session flow
1. Client loads the WASM runtime and generates an Ed25519 keypair in WASM memory.
2. Client calls `POST /init` with the public key.
3. Server creates an ephemeral session and returns a `session_id`, initial salt, VM program, and mutation order metadata.
4. Client executes the VM program, collects browser entropy, previews the mutation commitment, signs the heartbeat payload, and sends `POST /hb`.
5. Server verifies signature, hash chain continuity, behavioral sanity, mutation step parity, and gene commitment before returning the next salt and mutation order.
### Silent failure model
Invalid heartbeats are returned as `{"status":"ok"}` without mutation fields. This avoids giving attackers explicit feedback.
---
## Storage Backends
ChronoSeal supports multiple runtime storage backends configured via `db_type`:
* `sqlite-in-memory` — default ephemeral session storage
* `sqlite-disk` — persisted SQLite storage on disk
* `valkey` — alternative backend compatibility mode for future high-performance storage
---
## Deployment
ChronoSeal is intended to run as a systemd-managed Unix daemon with strict sandboxing and observable metrics.
See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for build, installation, and production deployment guidance.
---
## Security Model
ChronoSeal is a cost-raising attestations layer, not a perfect bot blocker.
ChronoSeal is designed to raise the cost of automation and replay attacks.
It protects against:
It helps defend against:
* replay attacks
* session cloning
* invalid signature injection
* broken hash chain continuity
* mutation tampering
* simple synthetic mouse and browser automation
- replayed heartbeats
- stale hash chain state
- forged heartbeat signatures
- mutation commitment tampering
- session cloning using only a stolen `session_id`
- simple scripted clients that do not run the WASM runtime
- basic browser automation with weak interaction simulation
It does not attempt to protect against:
It does not claim to stop:
* real users acting as bots
* server-side application vulnerabilities
* fully resourced adversaries with real browsers and hardware input devices
- real users intentionally acting as bots
- fully resourced browser farms
- attackers with complete control of a real browser and realistic input
- server-side application vulnerabilities
- account abuse outside ChronoSeal's attestation boundary
- long-term identity or fraud decisions by itself
See [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md) for the full threat model.
Privacy posture:
---
- Sessions are short-lived.
- The private key is generated in the browser runtime and is not sent to the server.
- ChronoSeal validates continuity and plausibility rather than creating persistent user identities.
- Invalid heartbeats are rejected silently to reduce oracle feedback.
Read the full model in [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md).
## Development
Run the standard checks:
```bash
cargo fmt --check
cargo check --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
```
Format:
```bash
cargo fmt
```
Build WASM during frontend/runtime changes:
```bash
wasm-pack build wasm --target web
rm -rf frontend/pkg
mv wasm/pkg frontend/pkg
```
Build release artifacts:
```bash
bash scripts/build.sh
```
Generate shell completion:
```bash
chronoseal completion bash > chronoseal.bash
chronoseal completion zsh > _chronoseal
```
## Troubleshooting
### Browser fails to load WASM
Rebuild the WASM package and make sure `frontend/pkg/chronoseal_wasm.js` and the `.wasm` file exist:
```bash
bash scripts/build.sh
```
The `.wasm` file must be served as `application/wasm`. The built-in static file service handles this for normal ChronoSeal deployments.
### `chronoseal health` fails
Check that the daemon is running and that the CLI is probing the correct bind address:
```bash
sudo systemctl status chronoseal
chronoseal health --bind 127.0.0.1:3000
curl http://127.0.0.1:3000/health
```
### Heartbeats return only `{"status":"ok"}`
That is the expected response for rejected heartbeats. Common causes include:
- invalid signature
- stale `prev_hash`
- stale `mutation_step`
- mismatched `gene_commitment`
- timestamp drift beyond the configured window
- insufficient mouse movement or pause data
- rate limiting
- expired session
Use local development logs and tests to debug integration issues. Avoid debug logs in production.
### SQLite disk mode cannot persist state
Ensure the daemon user can create and write the configured database path:
```bash
sudo mkdir -p /var/lib/chronoseal
sudo chown -R chronoseal:chronoseal /var/lib/chronoseal
```
Use:
```toml
db_type = "sqlite-in-disk"
db_path = "/var/lib/chronoseal/chronoseal.sqlite"
```
### Config changes do not apply
Check precedence. CLI flags override environment variables, environment variables override config files, and config files override built-in defaults.
Print the effective config:
```bash
chronoseal config check --format yaml
```
## Further Reading
* [Architecture](docs/ARCHITECTURE.md)
* [API Reference](docs/API.md)
* [Deployment](docs/DEPLOYMENT.md)
* [Threat Model](docs/THREAT_MODEL.md)
* [Design Philosophy](docs/DESIGN-PHILOSOPHY.md)
* [Privacy Policy](docs/PRIVACY%20POLICY.md)
* [WASM Build](docs/WASM_BUILD.md)
* [Refactoring v0.6.0](docs/REFRACTORING-v0.6.0.md)
- [Architecture](docs/ARCHITECTURE.md)
- [API Reference](docs/API.md)
- [Deployment Guide](docs/DEPLOYMENT.md)
- [Threat Model](docs/THREAT_MODEL.md)
- [Design Philosophy](docs/DESIGN-PHILOSOPHY.md)
- [Privacy Policy](docs/PRIVACY%20POLICY.md)
- [WASM Build Guide](docs/WASM_BUILD.md)
- [Refactoring v0.6.0](docs/REFRACTORING-v0.6.0.md)
- [Contributing](CONTRIBUTING.md)
- [Security Policy](SECURITY.md)
## License
ChronoSeal is licensed under either of:
- MIT, see [LICENSE](LICENSE)
- Apache-2.0, see [LICENSE-APACHE](LICENSE-APACHE)
at your option.