bmux_presenter_runtime 0.0.1-alpha.4

Authoritative presentation host and bounded TLS participant transport
# bmux_presenter_runtime

Application-owned authoritative presentation engine, shared by standalone and
BMUX-managed deployments. This crate adds no presentation domain behavior to core.
Plugin implementations call `Host` and expose generated BPDL operations; the
`protocol` messages here are exclusively the standalone TLS transport contract.

## Stable integration API

- `Host::new(Deck, Vec<Asset>, HostConfig)` validates a bundle and starts a new run.
- `Credential::generate(Scopes, Duration)`, `Host::add_credential`, and
  `Host::revoke_credential` establish private run-local principals. Store secrets
  privately. Reconnect always authenticates again; a participant ID is not a secret.
- `Host::authenticate(version, secret, mode)` creates a participant;
  `disconnect` releases connection resources. Independent views retain state and
  committed surfaces per private credential across reconnect, with one connected
  independent view per credential. Issue separate credentials for distinct views.
  `next_action_id` returns the next
  credential sequence number. Multiple devices sharing a credential share ordering.
- `snapshot` explicitly bootstraps/resynchronizes any authorized participant,
  including submit-only. `poll` returns unchanged cursors or complete bounded
  snapshots; submit-only has no ongoing polling subscription. No streaming API is
  assumed. Public read-only audience access requires `public_audience: true`.
- `submit(Submission { action_id, expected, action })` enforces mode, scope,
  run/deck/state cursor, rate, payload bounds, and committed surface geometry.
  Private navigation/demo/effect scopes are independent of speaker-note access.
- `asset` distributes only audience-referenced opaque resources in bounded chunks.
- `reload` validates the replacement bundle, then calls
  `Owner::prepare_reload(&self, &Deck, &[Asset]) -> Result<Box<dyn Owner>, HostError>`
  on the live owner with the new validated owner-local assets. The returned candidate
  must be isolated: retain values only for matching `(block ID, linked component
  type, state version)`, with no mutable handles shared with the active owner.
  `Owner::reconcile_reload(&mut self, OwnerContext) -> Result<Vec<MirrorFrame>, String>`
  rebuilds all shared, connected independent and retained independent geometry on
  the candidate before publication. It defaults to `scene`; `prepare_reload`
  defaults to `Invalid`, preserving source compatibility without inventing cloning.
  `reload_with_owner(deck, assets, Box<dyn Owner>)` still accepts an app-prepared
  candidate directly. Any preparation/scene failure preserves the active owner,
  deck, assets, navigation, cursors and committed surfaces; no effects replay.
- `Host::set_owner(Box<dyn Owner>) -> Result<(), HostError>` prepares and validates
  initial shared and connected independent scenes before installing the owner.
  `Owner::scene(&mut self, OwnerContext) -> Result<Vec<MirrorFrame>, String>` defaults
  to empty and is projection-only: it must never invoke effects. The host calls it
  on independent join and navigation, not on polling or viewer resize. Reload
  uses the candidate-only `reconcile_reload` hook (defaulting to `scene`).
  A reload owner must already understand the replacement deck identities; otherwise
  projection fails and the host retains the old bundle. Callback diagnostics are
  not exported. `MirrorComponent::new` validates a borrowed scene and implements
  the canonical layout/paint/event/revision lifecycle; map input using its exact
  successfully committed `LayoutNode` with `input_point`.
- `Owner` is trusted linked Rust. `OwnerContext.instance` is `shared` for shared
  ordering and credential-local for independent instances across reconnect. `OwnerUpdate` returns
  a bounded outcome and complete committed public surface batch. Never render
  private notes into audience surfaces. Generic viewers never activate Rust code.
- `commit_surfaces` publishes owner-committed structured BMUX scene captures.
  `MirrorFrame::capture` accepts a BMUX `Frame` plus reconciled `ImageScene`;
  `MirrorFrame::paint` reconstructs through `PaintCx`, not ANSI. `placement` and
  `CanvasPlacement::input_point` clip/letterbox the fixed owner canvas. Publish
  input geometry only after successful viewer presentation. Input includes the
  run/deck/state cursor and committed surface revision.
- `SourceLoader::{load_markdown, prepare}` accepts bounded local Markdown or
  linked decks, reads images beneath an explicit canonical root, normalizes image
  payloads, and invokes `WasmMermaidRenderer` (never the native renderer).
  Supply the embedded renderer and call source preparation outside the live
  host lock. WASM enforces timeout/memory/concurrency limits without a helper
  executable. Building this crate requires `wasm32-unknown-unknown`.
- `transport::{serve_tls, serve_local}` accept owned Tokio listeners, shared host,
  bounded network settings, and watch-channel shutdown. TLS config helpers parse
  bounded explicit PEM chains/keys/roots. Local plaintext requires loopback on
  both sides; remote TLS verifies certificate roots and server name.
- `transport::Client::{connect_tls, connect_local, authenticate, request}` provides
  one bounded in-flight exchange, no automatic replay, and poisons interrupted
  connections. Snapshot decode validates mirror scenes before exposing them.

## Delivery and privacy semantics

Action IDs start at 1 and increase per credential, surviving reconnect within a
live run. Retained identical submissions return their original success/error;
changed retained payloads return `ActionConflict`. IDs below the high-water mark
that have been evicted return `OutcomeEvicted`, never execute again. After eviction
clients must fetch authoritative state and explicitly reconcile external outcomes;
this is not durable exactly-once execution. A new host run has fresh identity and
requires explicit new actions. Never replay uncertain effects into a new run.
Owner calls consume the state revision before execution, even when their outcome
is uncertain. Polling/snapshots never invoke effects. The owner must return only
public, bounded outcomes; private external diagnostics should stay owner-local.

The audience projection strips notes, source locations, custom configuration,
extra metadata, Markdown link destinations/titles/references/autolinks and raw HTML.
Markdown stays rich: source-range edits preserve shared renderer syntax for inline
styles, lists, tables, code, math and footnotes; unsafe syntax exposed by reparsing
fails closed. Inline and block images use only authorized opaque asset IDs;
unreferenced assets are not served. Only exact `light`/`dark` theme names survive;
unknown names reject preparation. The local loader normalizes inline image assets
under the same bounded root policy as block images.
Standalone transport version **2** explicitly selects these richer projection
semantics; version 1 authentication is rejected. Plugin BPDL compatibility must be
selected by the owning plugin; these standalone messages are not plugin IPC.
Visible authored labels, code, Mermaid content, titles, authors, IDs, and custom
names are public content: authors must not put secrets there. Custom configuration
is never activated from an audience deck. Notes are a separately scoped field.

Limits cover messages, decks/notes, assets/cache bytes, frame/canvas/image decoded
sizes, surfaces, principals, participants, action retention, action size, request
rates, connections, handshake/read/write deadlines. Networking retains one request
per connection and uses bounded admission rather than unbounded queues. Owner
callbacks are synchronous trusted application code and must not block or spawn
unbounded work; asynchronous demo lifecycle management belongs to the application.

## Validation/handoff

Behavior tests cover auth/modes, private wire projection, shared/independent state,
reconnect action dedup and uncertainty, eviction, atomic reload, malformed mirrors,
all style bits, clipped placement, real loopback TCP and TLS certificate validation.
Follow-up coverage adds rich Markdown privacy/opaque inline images, immutable
candidate preparation, compatibility-key retention/reset, shared/live/cached
instance reconciliation, unknown theme and oversized asset atomicity, slow peer
timeouts and snapshot resync. Existing uncertain-effect reconnect/eviction coverage
is retained. Focused rustfmt and source/diff inspection only were run in this lane;
all cargo builds, clippy, tests and dependency validation belong to the coordinator.
The `bmux present` command/plugin adapters belong to their assigned integration lane.