Language-neutral WASM application authority · explicit browser boundary

Make the browser a mechanism, not a second application.

Limen gives the browser a narrow job: carry semantic events, apply a projection, and perform explicit effects. Authoritative application state and meaning live behind a WebAssembly boundary, in an engine that owns the state, legal transitions, capabilities, obligations, and interpretation of evidence.

This website’s reference engine is F# compiled to .NET WebAssembly. The boundary itself is language-neutral: the same contract is intended for C#, Rust, and other strongly modelled WASM engines.

This site is a consumer of Limen, not a mockup of it.

  • application state: WASM engine
  • this site’s engine: F#/.NET
  • browser authority: Limen
  • markup: static HTML

Why the boundary exists

Hard UI problems are usually authority problems.

The issue is not whether JavaScript can update a span. It can.

Legality

Can this action happen now?

Release approval depends on evidence. Deployment depends on approval. A disabled button should reflect that decision, not make it.

Evidence

Is this response still current?

Two requests overlap. The older response arrives last. Without correlation and explicit state, stale evidence silently wins.

External effects

Did the write fail, or do we not know?

A timeout after dispatch is not failure. Treating it as failure and retrying blindly is how duplicate effects are created.

Placement

Which layer is allowed to decide?

HTTP is browser mechanism. Interpreting 409 is application meaning. Focus control is not currently a Limen capability. Those distinctions are the architecture.

Framework flexibility versus architectural constraint

Fewer legal places for behavior to live.

React and Angular make the right thing convenient. Limen’s goal is to make the wrong thing structurally difficult.

Powerful frameworks

Many ways to build it

React and Angular are mature and capable. They give teams flexible mechanisms and let each team assemble its own architecture.

Constrained architecture

One place for meaning

Limen fixes where application meaning, browser mechanism, appearance, and structure go, so a misplaced decision is visibly wrong.

Enforcement

Checked, not just advised

Types, the protocol, and repository checks reject boundary violations. Some checks run today; more are accepted and in progress.

This is a difference in design goals, not a measured ranking. Why Limen, and where React and Angular are stronger today →

Self-hosting proof

The site follows the architecture it describes.

HTML and CSS remain browser-native. Limen turns interactions into plain messages and performs browser effects. A tiny transport loads the .NET WebAssembly runtime. Every application decision on the interactive pages lives in the F# engine.

The npm package itself is still a TypeScript browser kernel. The F# WASM site engine is a real consumer of that package boundary, not code shipped as part of the kernel.

  1. 01
    HTML/CSS define document structure and presentation.
  2. 02
    BrowserKernel carries semantic events and applies projections.
  3. 03
    WASM transport serializes one message in and one response out.
  4. 04
    F# engine owns state, legality, obligations, effects, and view projection.

Live problem

A release is not a collection of booleans.

Resolve evidence, obtain authority, then test what happens when deployment evidence becomes uncertain.

Release gate

Not started
TestsUnverified
SecurityUnverified
ApprovalNot approved
DeploymentNot started

The buttons are not the rules. F# projects capabilities such as canApproveRelease and canDeployRelease from authoritative state. Limen only applies them to the DOM. A timeout becomes ReconciliationRequired, which removes deployment capability until new authoritative evidence arrives.

Why a strongly typed engine

The difficult part becomes ordinary typed code.

The engine never imports a browser API. F# is this site’s reference language; Rust enums and generated C# closed types are the accepted equivalents.

This site’s F# engine: state that cannot lie about deployment
type DeploymentState =
  | NotStarted
  | InFlight of CorrelationId
  | Deployed
  | DeploymentFailed of reason: string
  | ReconciliationRequired

type ReleaseState = {
  Tests: EvidenceState
  Security: EvidenceState
  Approved: bool
  Deployment: DeploymentState
}
Browser-side wiring has no application decision
await new BrowserKernel(
  new WasmSiteTransport(),
  document,
  diagnostics
).start();

// No release state.
// No approval rule.
// No retry policy.

What follows from the boundary

Structural consequences, not benchmark claims.

The evidence page separates what is enforced from what remains unmeasured.

Application state has one owner

The WASM engine decides — F# on this site. The DOM is projection output and browser-local state remains browser-local.

Effects are evidence

The browser reports classified outcomes. The engine decides what those outcomes mean to the application.

Capabilities are projected

The UI does not reconstruct permission by peeking at text, CSS classes, or unrelated flags.

The boundary is executable

This site crosses it for real: static HTML → Limen → serialized protocol → F# WebAssembly → projection.

See exactly what is measured, structural, provisional, and still unknown →

Go deeper

Make the hard cases fail in front of you.