# Free4AllHub circuit workbench

This teaching workbench pairs an original browser interface and schematic renderer with a hardened, isolated CircuitJS solver derived from pfalstad/circuitjs1 commit **8ac55f22a03606579b822b3dccd4dc10de1ddc5b** (source version 5.0.4). It is a modified teaching subset, not the full upstream CircuitJS visual editor, not a professional design-verification tool, and not a Multisim/SPICE file converter.

## Verified coverage — 7 November 2026

- **82 adapter tests passed:** circuit/worksheet schemas, accepted fixtures, reference calculations, message/session guards, malformed-input bounds and controller tests with a simulated DOM. These tests do not execute CircuitJS.
- **13 analytical tests passed:** independent closed-form reference calculations. These are not simulator observations.
- **29 real-engine fixtures passed:** the modified CircuitJS solver, including R/L/C, voltage/current sources, switches, periodic-source settings, initial and saved state, native XML round trips, topology failures and component/matrix bounds.
- **Desktop Chromium workflows passed:** actual solving, editing, downloading, fresh-file reopening and revision. Desktop schematic, readings, chart and controls were visually inspected.

The browser divider measured 2.5 V and 2.5 mA with two 1 kΩ resistors. Changing the lower resistor to 2 kΩ gave 3.333333 V. The downloaded native file reopened in a fresh session and reran; changing that resistor to 3 kΩ gave 3.75 V, and the second native download preserved the revision.

The browser RC runs used 100 µF and 5 V with 10 kΩ and 20 kΩ. Each downloaded worksheet contained 50 actual observations. At the recorded simulated time of approximately 1.0000000000000007 s, measured capacitor voltages were **3.1596827888 V** (10 kΩ) and **1.9665883801 V** (20 kΩ). The separately calculated references at that same time were 3.1606027941 V and 1.9673467014 V. The references were not substituted for solver readings.

Fresh worksheet reopening preserved notes and made the historical chart and all saved observations available without starting the engine. Engine controls stayed disabled until Preview; Preview began a new run at t = 0 and cleared the old observations. Invalid JSON was rejected, and the next worksheet download remained byte-identical. Editing cleared old live results; Reset followed by two Advance actions reached 0.2 s; Close removed the simulator and disabled Run.

The engine is SHA-256 `196db4e2359d93baf8a107cfc615a5128e78be7cb553ed282a35690b0a64176d`. The opaque sandbox, denied iframe device permissions and parent CSP were inspected. The source archive was downloaded and checked in the browser before the final documentation-only refresh; the final archive is independently hashed and rebuilt from its extracted source. Rebuilds reuse the same verified, locked toolchain rather than claiming a second clean dependency installation.

**Not verified:** narrow-screen/mobile layouts, physical-phone use, screen-reader use, real-beginner usability or physical hardware. No full network capture, independent security certification or guaranteed CPU/process isolation is claimed. Browser coverage is for the documented teaching workflows, not every possible accepted circuit or full CircuitJS/Multisim equivalence.

## Workflows and file semantics

- Voltage divider: 5 V across 1 kΩ + 1 kΩ; revise the lower resistor to 2 kΩ. The closed-form references are 2.5 V / 2.5 mA and 3.333333… V / 1.666666… mA, respectively. These are calculated references, not measurements.
- RC charging: 10 kΩ, 100 µF, explicit initial capacitor voltage 0 V and 5 V DC. The time constant is 1 s; double the resistor for 2 s. References use the **actual simulation time** reported by the engine, never elapsed browser time.
- Actual voltage and current must come from CircuitJS. The chart connects recorded solver samples; it is not a continuous trace. Named-node voltages are relative to ground. CircuitJS source voltage polarity differs from passive R/L/C polarity, and the interface states this.
- Each edit/import/preview/reset removes the old iframe, invalidates message generations and clears live readings. Old iframe messages cannot become results for a new circuit. A newer file/fixture request wins over an older asynchronous response.
- Preview and Reset start from the circuit’s authored capacitor initial voltage (`iv`) and inductor initial current (`ic`) at t = 0. Native XML can contain instantaneous capacitor voltage (`vd`) or inductor current (`i`); those fields are preserved in the draft and native export but **are not treated as a resumable timeline**. The engine is reset to initial conditions before a new run. A nonzero or unspecified RC initial voltage disables the built-in zero-start analytical reference.
- Native drafts use current CircuitJS XML. Supported legacy line text is parsed and normalized without discarding accepted fields. Native engine downloads preserve the exact validated XML returned by the engine. Files are detected by content, so XML in an upstream `.txt` file is accepted.
- The worksheet is JSON containing native circuit XML, notes and retained observations. Reopened observations are immediately available in a historical chart and expanded observation list, with simulator controls disabled until Preview. They are labelled historical, not newly measured. It is not a simulation checkpoint. A new run clears historical values. Up to the latest 1,000 component readings are retained to keep local worksheet files bounded.
- All exports are explicit browser downloads. The tab does not upload inputs, use an account, automatically save or retain work after reload. Reopen the downloaded file and rerun before relying on it.

## Supported input

Nine primitive types: resistor, capacitor, linear inductor, voltage source, current source, wire, ground, named node and simple switch. Inputs must have 1–128 components and an explicit ground. Native circuit files are at most 64 KiB; worksheets at most 256 KiB; note text at most 4,000 characters. The full validator is `core.mjs` and is shared with the engine bridge.

This edition requires a fixed 1 ms timestep, minimum step 1 µs, speed factor 1 and no adaptive-step or DC-on-reset flags. It supports source voltages/bias within ±50 V and current sources within ±1 A; R = 1 Ω–1 MΩ, C = 1 nF–1 F, L = 1 µH–100 H. Periodic source frequency is bounded to 50 Hz; this fixed time step is not intended for high-frequency analysis. Initial capacitor voltage is within ±50 V and inductor current within ±1 A. Nonlinear inductor saturation is unsupported. Coordinates and numeric tokens are bounded and canonicalized before the native parser.

Unsupported components, scopes, models, custom expressions/logic, nested subcircuits, audio/data/ROM sources, HTML, scripts, URLs, XML declarations/entities/comments and unknown attributes are rejected. Nothing is silently dropped to make an incompatible circuit appear to work. Ambiguous legacy pulse-source, zero-current-source and switch forms are rejected; their explicit supported XML equivalents remain available. Saved dynamic `vd`/`i` values may be larger than authored initial conditions, but are bounded to ±1e12 and reset before simulation. The stricter local limits mean many valid full CircuitJS files cannot be opened here.

## Isolation and limitations

The parent owns file inputs, downloads, notes and component controls. The engine is a single self-contained document in an opaque `sandbox="allow-scripts"` iframe without same-origin, navigation, forms, downloads, storage, popups or device privileges. Its bridge requires the live frame identity, a per-instance random token, generation, bounded command schema and request ID. The parent page CSP allows only its own scripts/styles/fixtures/frame and blocks workers, objects and form submission; the engine has a stricter no-network policy.

The adaptation removes upstream remote imports/sharing, Dropbox, service workers and persistence; unsupported menus/keyboard/file/clipboard/device paths are not part of this edition. Removed fonts, gallery examples and legacy images are not redistributed. The exact engine hardening and build record belongs in the adjacent source package.

A sandboxed iframe is **not guaranteed CPU/process isolation**. Bounds and fixed solver settings reduce risk; they are not a security certification. Bad wiring can produce solver errors. CircuitJS’s hidden electrical repair paths are disabled: unsupported ideal loops, shorted capacitors and source/inductor paths produce explicit errors rather than silently adding resistance or clearing energy. Close simulator or reload if it stalls, and download before leaving. No physical wiring, mains, battery, medical-device or safety-critical guidance is provided. Canvas graphics have text component/value alternatives; this does not establish a screen-reader or physical-phone usability audit.

## Rebuild original adapter

From the source package root, with Python 3 and Node:

    python3 scripts/build-adapter.py
    node --test tests/*.test.mjs

This copies only original adapter files into `dist/tools/circuits/`; it does not run a development server or engine. Follow the engine build README for the exact locked toolchain and serial hardened engine build. Do not run upstream `dist.sh` or its service-worker packaging unchanged.

## Rights and provenance

The combined modified engine/adapter is distributed under **GPL-3.0-or-later**, using the later-version option in CircuitJS’s GPL-2.0-or-later grant to combine it with Apache-2.0 matrix code. Original copyright notices remain. Upstream `package.json`’s ISC scaffold is not a relicensing of the program. Preserve all included GPL, Apache and MIT notices and the exact corresponding modified source and rebuild inputs.

The rest of Free4AllHub is separate aggregation and is not relicensed by this work. Original lesson fixtures retain their MIT license and notice; the original adapter is GPL-3.0-or-later. Your original circuit designs and notes are not claimed by the software publisher. See `THIRD-PARTY-NOTICES.txt` and the source archive for the full notices, changes, input and output hashes.

Comparison evidence: NI Multisim desktop official documentation reviewed 7 November 2026, https://www.ni.com/en-us/shop/product/multisim.html . This is a narrow task comparison, not hands-on competitor testing, numerical equivalence or a savings claim. Multisim Live’s ended service is not the compared product.
