Skip to content

Glossary

Terse, exact definitions of Bynk’s load-bearing terms. Each links to its fuller reference page where one exists.

A keyed, stateful entity whose state lives in store fields and changes only through writes inside its handlers. See Agents.

A bounded context: an isolated module with its own services, agents, and provided capabilities, reachable only across an explicit boundary.

A named group of handlers (on call, from http, from cron, from queue) declared inside a context. See HTTP.

An interface of effectful operations a context may depend on. See Capabilities & providers.

A provides block implementing a capability, optionally given other capabilities it uses. See Capabilities & providers.

The atomic persistence of a handler’s store writes. A handler’s := writes are staged and committed together when it returns, after invariants are checked; a faulting handler commits nothing. See Agents.

A compiled type carrying a unique tag so values of distinct Bynk types cannot be interchanged in the emitted TypeScript; how opaque types stay distinct. See Emission.

A type whose representation is hidden outside its defining module; constructed and inspected only through its API. See Type system.

A base or named type narrowed by a where predicate, e.g. Int where Positive. See Refined-type API.

A tagged union of variants, each optionally carrying a payload. See Type system.

A product type of named fields, each with a type and optional default. See Type system.

A sum type whose variants all carry no payload. See Type system.

A built-in constraint used in a where clause (Positive, NonNegative, InRange, Matches, MinLength, …). See Refined-type API.

The compile-time rule by which a literal that provably satisfies a refined type’s predicate is accepted directly (lowering to an inline brand cast), with no Result. See Refined-type API.

.of validates at run time and returns a Result — the constructor for both refined and opaque types. .unsafe constructs without a check and is opaque-only, usable within the opaque type’s defining commons; a refined type has no .unsafe (ADR 0182). See Refined-type API.

A type with a defined implicit zero value, letting an agent state field omit an initialiser. See Agents.

The type of a computation that performs effects; produced by handlers and capability operations and sequenced with <-.

Errors-as-values types: Result is Ok or Err; Option is Some or None. See Type system.

A base type for a span of time, written as a unit literal (5.minutes); composes with Instant. See Type system.

A base type for an absolute point in time, minted by Clock.now(); no literal, orderable but not numeric, advanced by a Duration. See Type system.

A lazy read over a store’s storage, carrying the same combinator vocabulary as the eager List methods but dispatched by receiver provenance; non-storable and non-boundary. See Type system.

A test-only expression that fabricates a valid inhabitant of type T drawn from its refinement domain, optionally pinned to a chosen value (Val[T](v), refinement-checked at compile time). Replaces the retired Mock[T] (v0.114). See Testing.

A generative test, the sibling of case in a suite: for all x: T binds x to a generated inhabitant of T and the body’s expects must hold across many. On failure it reports a shrunk counterexample and a seed to reproduce. See Testing.

A function’s requires (precondition) and ensures (postcondition) clauses — the invariant predicate attached to a pure fn. Checked at every call in the dev/test build and generated against by the runner; stripped from the deploy build. A contract is a property that is always on. See Contracts.

A function precondition: requires <name>: <pred>, a pure Bool over the parameters. Guards the call and filters the runner’s generated arguments (like a for all … where). result is not in scope in a requires.

A function postcondition: ensures <name>: <pred>, a pure Bool over the parameters and result. Checked at every call and generated against by the runner.

The contextual binding for a function’s return value, in scope only inside an ensures predicate (the awaited element for an Effect return). Everywhere else result is an ordinary identifier.

An agent step invariant: transition <name>: <pred over old/new>, the invariant predicate widened from a single committed state to the move between two. Declared beside an agent’s invariants and checked at the commit boundary (from the second commit onward). Unlike a contract, it is not attacked by the runner — a fabricated agent state is valid but not necessarily reachable.

The contextual bindings inside a transition predicate: old is the last committed state, new the state the current commit would persist — each the agent’s state record (old.status, new.balance). Special only inside a transition; everywhere else old/new are ordinary identifiers.

An expect over a capability seam, inside a case — asserting interaction (that Cap.op was called, with what arguments, how often, in what order) rather than a value. The sugar forms: called, never called, called once / called <n> times, called … with <pred>, and A.op before B.op. Calls are recorded automatically at the seam in the test build, so a pure-observation case needs no stub. A with <pred> is the invariant predicate over the operation’s parameters, in scope by name.

The observation escape hatch: trace(Cap.op) yields the recorded calls of a capability operation as a List of per-operation records (fields = the operation’s parameters), in call order, asserted with the ordinary List surface. A test-only builtin — an ordinary identifier outside a case.

The subject of an observation: a capability and one of its operations, named, not called (no argument list) — e.g. Logger.log in expect Logger.log called.

How much of the real world is present when a case runs, set by an as <tier> clause on the case (or suite) header — one of unit / integration / system. A tier is one body promoted, not a distinct kind of test: promotion changes only the header, never the body. as on the suite sets a default the case may override (case wins); tiers are a case-only affordance (a property has no tier — bynk.tier.property_has_tier). See Test tiers.

The three tiers, borrowed from the testing pyramid. unit (the default, elided) runs the unit in process with collaborators you control seam by seam (stub). integration runs its real collaborators within one context, no wire. system stands contexts up as the Workers they deploy as and wires them across the real serialise → JSON → deserialise edge; a system case must span ≥ 2 contexts (bynk.tier.system_needs_wire). Participants for integration / system are inferred from the consumes graph — there is no wires clause.

A per-seam test-time provider override: stub Cap.method(<pattern>) returns <value> | fails, at case or suite scope (precedence: case > suite > tier default). The left is a call pattern (the one predicate surface — _, literals, is, first match wins); the right is a value or fails, never a computed body. The sequenced form returns each [<outcome>, …] supplies one outcome per call, the last repeating. Capability-only. It substitutes a consumed seam of the unit under test — the supply leg of the seam triad (consumes declares, given requires, stub substitutes). Its own keyword since the keyword-hygiene batch (#548); formerly a pun on provides. Replaces the retired mocks block (v0.118), after which “mock” is gone from the language. See stub.

Project mode is a bynk.toml-driven directory layout (a src/tests split, bynkc test); legacy mode compiles a single .bynk file as a standalone unit, with no manifest. See bynk.toml manifest.