docs/waves/technical_architecture.md
Waves Technical Architecture
Version: v0.2 Status: Canonical direction document
Project Overview
Waves is a modern desktop WAP 1.0 browser emulator designed to execute WML decks with a native Rust runtime.
Core goals:
- deterministic WML runtime behavior
- host/runtime separation
- protocol fidelity through an in-process Rust transport stack
- fidelity with historical WAP browser behavior
Design Philosophy
Waves is an embeddable WAP runtime, not a DOM renderer.
Execution correctness is independent from:
- network transport
- latency/retries
- session negotiation
External Architecture Alignment
Waves architecture is intentionally aligned with modern browser engine split patterns:
- content/runtime semantics live in the engine runtime layer
- host/browser shell brokers external capabilities and UI side effects
- execution isolates failures via runtime error boundaries
Guidance references:
- Chromium process model and site isolation:
- WebKit2 architecture:
- WHATWG event loop + navigation model:
- WebAssembly security model:
System Architecture
1) Runtime Core (Rust)
Responsibilities:
- WML parsing
- deck/card model
- navigation stack
- softkey bindings
- variable context
- event dispatch (
onenter,ontimer) - layout model
- runtime lifecycle
Representative boundary:
fn load_deck(input: &[u8]) -> DeckHandle;
fn navigate(handle: DeckHandle, action: NavAction);
fn render(handle: DeckHandle) -> RenderTree;
2) Runtime Targets
Built as a shared Rust runtime with target-specific adapters.
Targets:
- native Rust embedding (preferred for Tauri backend integration)
- WASM (
wasm-bindgen/wasm-pack) for browser/webview hosts - local browser harness (
engine-wasm/host-sample)
Responsibilities:
- runtime deck/card execution
- deterministic layout and focus behavior
- render tree/list generation
3) Host Shell (Tauri)
Repository path: browser/
Responsibilities:
- windowing and input
- host process lifecycle
- transport request lifecycle management
- IPC bridge from UI to transport/runtime boundaries
- native runtime embedding path (when host chooses direct Rust integration)
Transport Strategy
Current state
Transport is handled by Rust (transport-rust/) as an in-process library invoked by Tauri commands.
Current transport responsibilities:
- HTTP and WAP fetch orchestration
- WSP/session framing and transport-protocol state
- WBXML decode/normalization
- gateway adaptation and error taxonomy mapping
- deterministic request correlation/logging metadata
- fetch destination policy enforcement for host-command requests (
fetch_deck)
Fetch destination policy posture (M1-17):
- default mode is
public-onlyforfetch_deckdestinations to reduce SSRF/internal probing exposure if renderer/UI code is compromised. - the host policy is authoritative: renderer-supplied request policy may tighten it but cannot enable private destinations.
public-onlynormalizes IPv4-mapped IPv6 addresses, rejects non-public literal targets, validates every DNS answer used by the HTTP connector, revalidates every redirect hop, and validates native WAP peer addresses.- developer override is explicit via
WAVES_FETCH_DESTINATION_POLICY=allow-privatein host environment; this is intended for local integration workflows only. Operator-configured gateway endpoints remain governed by host configuration after the original WAP destination is validated. - policy behavior is deterministic in transport error mapping (
INVALID_REQUESTfor blocked destinations) and does not alter engine navigation semantics.
Current protocol stack posture:
- default profile:
wap-net-core(native WDP/UDP -> connectionless WSP transport ingress) - extension profile:
wap-net-extremains future-gated for additional bearers, connection-oriented WSP/WTP, Push, and advanced session features - security profile:
wtls=disabled|active-minimalin current codepath, with transition decision tracked byT0-14andT0-21
Supported profile classes:
gateway-bridged: legacy gateway path retained as rollback posture and local smoke comparison lane.wap-net-core: active native WDP/UDP -> connectionless WSP path with mandatory selected-profile method support (Get/Post/Reply) and deterministic request state; WTP is not activated by this profile.wap-net-ext: future extension mode enabling additional bearers, connection-oriented WSP/WTP, Push, and optional advanced sessions after explicit gate decisions.
Transport profile decision rules:
- all transport behavior must be deterministic under a named profile
- all profile promotions are gated by completed protocol fixtures and ticket chain
- request/response contract to browser and engine must remain stable across profile changes
- profile moves require
docs/waves/networking-migration-readiness-checklist.mdgate completion for the relevantT0-08..T0-17items - protocol-native readiness uses
T0-18..T0-24implementation evidence, while exact WDP/WCMP/connectionless-WSP conformance remains gated byTRN-701,TRN-702,TRN-703, andWSP-801/802/804/805; WTP evidence becomes release-gating only when the extension profile claims connection-oriented WSP - transport-adjacent TCP posture for
RQ-TRX-009is declaration-gated indocs/waves/TRANSPORT_ADJACENT_SPEC_TRACEABILITY.mdand tracked byT0-12 - SMPP adaptation (
RQ-TRX-010,WAP-159) is currently deferred byT0-13; no transport-rust SMPP mapping path is active in MVP profile - canonical profile-state and rollback criteria are defined in
docs/waves/NETWORK_PROFILE_DECISION_RECORD.mdand validated bynode scripts/check-networking-profile-gates.mjs
Request example:
{
"action": "fetchDeck",
"url": "wap://example.com/login.wml"
}
Response example:
{
"status": 200,
"contentType": "text/vnd.wap.wml",
"body": "<wml>...</wml>"
}
Protocol Evolution Plan
- Keep transport-rust as the single transport implementation.
- Expand protocol coverage incrementally behind tests and fixture-based checks.
- Preserve strict boundary ownership: transport handles network/protocol/decode, engine handles runtime/rendering.
- Current networking-lane regroup priority order is
T0-19 -> T0-18 -> T0-20 -> T0-22 -> T0-21, with migration dependencies tracked inT0-08..T0-17. - Future transport profiles should update both this plan and
docs/waves/networking-implementation-checklist.mdbefore feature introduction.
Source handling path for transport specs
Spec-processing flow used by networking work:
- New files are staged in
spec-processing/new-source-material/. - Parsed markdown output for review appears in
tmp/docling-new-source-material/. T0-16/T0-17enforce canonicalization, conflict resolution, and deferment policy.- Canonical PDFs for implementation are then sourced from
spec-processing/source-material/.
Renderer Correctness Gate
Do not expand protocol complexity until deterministic runtime execution is proven with fixtures.
Minimum gate:
- 20+ offline fixture decks
- multi-card navigation
<do>softkey behavior- timer-driven
<onevent> <setvar>behavior- forward/back stack behavior
Execution targets for gate:
- Tauri host (native runtime or WASM adapter)
- browser harness (
engine-wasm/host-sample)
WTLS Strategy
Initial plan:
- simulate handshake semantics internally
- pass decrypted WSP payloads to runtime
- use modern TLS at bridge boundaries where needed
WTLS modernization is deferred until transport parity is achieved.
Future Targets
Because runtime is Rust-native, future host targets may include:
- Android (JNI)
- iOS (UniFFI/Swift interop)
- CLI runtime
- WASM PWA host
- headless simulation/test harnesses
Initial Roadmap (Planning)
- Tauri bootstrap: ~1 day
- WASM runtime MVP: ~2–3 weeks
- fixture suite expansion: ~3–5 days
- Rust WBXML decode: ~1 week
- Rust WSP parse: ~1–2 weeks
Repository Mapping
- Runtime/WASM:
engine-wasm/ - Host shell (Tauri):
browser/ - Transport library:
transport-rust/ - Architecture docs:
docs/
Summary
Waves is runtime-first.
- deterministic WML execution comes before protocol rewrite
- host shell remains replaceable
- transport capability expansion proceeds in bounded phases