Skip to main content

Public simulator demo

BHTune Demo mode is a restricted web experience for trying the tuning workflow without connecting to a DCS, PLC, OPC DA gateway, or live control loop. It uses the same MRFT engine as Full mode, but every accepted run uses the in-process simulator and the server enforces the restriction before any driver or plant configuration is opened.

What the demo can do

Demo mode provides:

  • the built-in, read-only template catalog;
  • bounded simulator settings and process/controller choices;
  • one simulator tune per visitor at a time;
  • live PV/MV progress over Server-Sent Events;
  • private run history with detail, duplication, export, cancellation, and deletion.

It does not provide OPC server discovery, tag browsing or reads, configuration changes, template mutation, notes, drafts stored on the server, PID write-back, API documentation, or any other live-plant operation. Demo requests containing those fields are rejected rather than silently ignored.

The Demo tune page is clearly labeled and keeps the controls that affect simulator behavior: visitors can choose a built-in template, process/controller type, relay and cycle settings, noise protection, and bounded simulator physics. Controls that require live equipment are omitted from the page rather than presented as no-op options. The interface presents the simulator boundary, history limit, and session lifetime in one persistent Demo notice rather than repeating the same warning on each page.

Every run is stored with the stable display identity Simulator demo. It is not a plant tag and does not change the simulator driver's internal Sim.PV and Sim.MV tags.

Visual workflow

The visual Web UI reference explains the shared shell and Full-mode screens in detail. These four Demo captures show the restricted path end to end; the operational and security requirements below remain authoritative if images are unavailable.

BHTune Demo simulator tune form with the fixed policy notice and bounded fields
The Demo form exposes bounded simulator controls and makes live-plant features unavailable.
BHTune Demo visitor history list showing simulator runs for the current session
History belongs to the current anonymous browser session and is owner-scoped by the server.
BHTune Demo live simulator run with a streaming PV and MV trend
The Demo trend uses the same live stream and cancel workflow as Full mode, without plant access.
BHTune Demo completed simulator run detail with calculated results and diagnostics
Completed Demo runs retain results, samples, and diagnostics for the current visitor.

See Web UI overview and Runs and history for the shared navigation and run-detail behavior.

Privacy and identity

The demo uses an opaque, host-only __Host-bhtune_demo_session cookie to separate visitors. The cookie is an isolation token, not a user account: it does not identify a person, provide authentication, or support account recovery. Only a one-way hash of the token is stored.

The cookie is secure, HttpOnly, SameSite=Strict, scoped to /, and expires after 24 hours. A session database row is created only when the browser starts its first accepted run. Demo sessions and their owned runs are removed after expiry, and the browser's local form draft also expires after 24 hours.

Sharing a browser profile or its cookies shares the same demo session and its history. Use a private window or a separate browser profile when two people need independent demo histories. Run identifiers are not authorization credentials: every history, stream, cancel, export, and delete operation is scoped to the current session, and another session receives the same 404 response as an unknown run.

Resource limits

The public service applies bounded defaults and validated ceilings to prevent one visitor from turning a demonstration into an unbounded workload:

ControlLimit
Active runs per visitor1
Active runs globally8
Accepted starts per token and client IP6 per 10 minutes
Accepted runs per browser session10
Retained terminal runs per visitor10
Current Demo-owned run rows5,000
Simulator poll interval200 ms
Run timeout30 seconds
JSON request body32 KiB
SSE connections per visitor/global2 / 32
SSE lifetime45 seconds
Ordinary concurrent requests64
Ordinary request timeout10 seconds

These are fixed application-owned limits, not public tuning controls. A deployment configuration may declare the same values so startup validation can detect drift, but it cannot weaken or expand the contract. The controls are fairness and availability safeguards, not a promise of volumetric denial-of-service protection. Network-level filtering, TLS termination, and upstream abuse controls remain necessary for an Internet-facing deployment.

Simulator contract

The capability document and server-side request validator use the same bounded simulator contract:

InputDefaultAccepted values
Relay amplitude10%1–20%
Cycles to skip / count1 / 20–2 / 1–3
Noise protection0 s0–3 s
Process gain1.0magnitude 0.1–5.0; zero is rejected
Time constant0.5 s0.05–5 s
Dead time1.0 s0–2 s
PV/MV range0–100endpoints -1000–1000; ordered span 1–1000
Initial PV/MV50 / 50within the corresponding configured range
Measurement noise00–5% of the configured PV span
Random seed00–2,147,483,647

Positive gain requires Reverse action and negative gain requires Direct action so the simulated loop always uses negative feedback. The browser derives that direction from the gain; the server independently verifies it.

Self-hosting requirements

Run Demo mode as a dedicated single-replica service with a dedicated SQLite database. Do not point it at a Full-mode database, a production configuration, or an OPC gateway. Keep the application behind the intended reverse proxy and publish only the selected host port. State-changing browser requests require the exact configured origin. Loopback HTTP is suitable for local development; non-loopback access must use the configured HTTPS reverse-proxy origin, not the application's bound HTTP port directly.

The server trusts a client IP only from the configured immediate proxy peer and only through the dedicated X-BHTune-Client-IP header. The reverse proxy must delete any inbound copy and overwrite it with the address it observed. Direct requests, malformed values, duplicate headers, and forwarding chains must not be treated as the visitor's original address. Quotas use an IPv4 address directly and group IPv6 clients by their /64 network.

Use an immutable container digest for deployment rather than a mutable tag. Keep one local previous-image reference and a timestamped database backup so a failed migration or local health check can restore both the executable and its data. A public ingress failure with a healthy local backend is a proxy or network incident, not a reason to discard healthy application state. The deployment pipeline verifies the signed build provenance certificate and image subject against the BHTune repository, the main-branch Docker workflow, the triggering commit, and the resolved image digest before it invokes the host rollout wrapper. The deployment runner downloads a pinned, checksum-verified GitHub CLI release for this verification instead of relying on the older distribution-package version in its Alpine base image; this keeps Sigstore trust-root support reproducible across runner updates. The verifier waits for the attestation record after the image tag appears because GHCR image publication and GitHub attestation indexing are eventually consistent. The Docker workflow and Woodpecker deployment definition are both image-triggering paths: changing either one publishes a matching immutable commit image before deployment, preventing a deployment-only fix from being stranded without a corresponding GHCR artifact.

Security boundary

Demo mode is a server-side route and validation boundary, not a collection of hidden browser controls. The Demo router does not mount Full-only endpoints, and private responses use no-store caching and no-index headers. State-changing browser requests require the exact configured origin, and the service sends framing, content-type, referrer, resource-policy, permissions, and content-security headers. The browser also fails closed if the capability document is missing or malformed, so incomplete server metadata cannot enable a broader interface or weaker client-side restrictions.

The demo is intentionally anonymous and has no accounts, CAPTCHA, multi-replica quota coordination, or remote-plant access. Treat the session cookie as bearer isolation state: anyone who obtains it can use that browser session until it expires. Do not place secrets, production data, or live controller connectivity in the Demo deployment.