# CVN > A kernel/host framework: a total, synchronous update over a Model, effects as Cmd data, hosts that perform them through declared ports — and the gates that keep it that way. ## Docs - [Concepts](/concepts): One plain object. The kernel reads it through a **state cell** and writes it with `commit(patch)` or `replace(next)`; every write notifies subscribers. Nothing in the kernel keeps its own copy — a local `let state = getState()` in an async function is a snapshot that silently goes stale after the first `await`, and it was the single most repeated defect in the port CVN came from. - [Dispatcher](/dispatcher): Five behaviours, each pinned by a test in the package: - [Gates](/gates): A claim about the code that is not a test is a box someone ticked. CVN ships its gates as functions so a repository's tests can assert them against its own files. - [Hosts — the contract](/hosts): Two hosts ship with the package: [`@enc-protocol/cvn/node`](/hosts/node) and [`@enc-protocol/cvn/web`](/hosts/web). A third, native, lives in `zooid-native` — [how to build it](/hosts/native). - [Porting an app onto CVN](/porting): The port CVN came from moved a 7,400-line application runtime into this shape without a rewrite. The order below is the order the obstacles fell; each step was blocked by the previous one. - [The rules](/rules): Each of these was paid for. They are stated as they were learned. - [Runtime](/runtime): `runAction` receives the **dispatcher's** `perform`. A runner built on any other `perform` — say the host's own — records nothing in this dispatcher: every Cmd is performed at once, the drain is empty, and `performNow` is a declared capability nobody exercises. This happened in the port CVN came from, and it was found only when a Cmd routed through that `performNow` changed nothing. The runtime binds it for you; if you build a runner by hand, the port gate asserts the binding. - [Testing cadence](/testing): Three tiers, three costs, one rule. - [Native — extending CVN in ](/hosts/native): This is the guide for the native adopter. The work is in `../zooid-native`; CVN stays where it is. Nothing here requires touching the framework — that is the test of whether the framework is one. - [Node host](/hosts/node): The store is in memory unless one is handed in. Timers and the clock are node's; randomness is `node:crypto`. This is the host the node test tier uses to drive a kernel with no DOM anywhere — the rule in the repositories CVN came from is **no DOM emulation in node**: a kernel that needs a document to be tested has a host leak. - [Web host](/hosts/web): The store is `localStorage` unless a **Storage-shaped** object is handed in. That is also how the web host is tested in node without emulating a DOM: the contract is four methods (`getItem`, `setItem`, `removeItem`, `key`/`length`), and an object with those four *is* the dependency. If there is no `localStorage` and nothing is handed in, construction **throws** — a silent memory fallback would be a host that forgets on reload while claiming to persist.