# OpenVSP / VSPAERO integration

## Save a source to Aero Model

The blue **Save to Lift/Drag Model** button beside **4. VSPAERO results** saves the
OpenVSP result record and its Aero Model sources together into the active JETcentral
aircraft JSON. Main must remain open with the original aircraft; changed aircraft
and read-only projects are rejected without a partial save. The save publishes its available
coefficients, reference dimensions, flight conditions and plotted samples to the
active aircraft's Aero Model library. New saves publish one source from the enabled
lift-coefficient datasets and enabled drag-polar datasets, fitted together in each
graph. Historical records without enabled-fit selections retain per-condition sources.
A saved Aerodynamics run can be published while another native
analysis is selected. Open the page from Main and keep Main open; stale aircraft
handoffs and read-only projects cannot write. Ordinary result or plot saves do not
change an Official selection.

Choose Official lift and drag sources in the [Aero Model widget](widgets/aero-model.md).
Those selections automatically drive performance, mission and constraints;
simulator calculations remain separate. Newly completed runs retain solve-time geometry
provenance; historical unsigned results are clearly unverified. Solver lift samples
do not establish stall CLmax, and the saved source retains the solver's drag-model
limitations.

Open the OpenVSP widget in the CFD pane. The page receives an aircraft snapshot;
reopen it after changing the aircraft in Main. You can also load JET JSON or JET11/JET12 workbooks through the shared loader.
On opening or loading an aircraft, a cancellable worker converts it to VSP3 and displays the converter's blue wireframe. The preview uses the sampled sections actually written to VSP3, including a single centerline vertical fin. Lifting surfaces and fuselage profiles now come from the common renderer's geometry definitions; the preview remains the dedicated blue OpenVSP wireframe. Native VSPAERO solver panels are generated at analysis time; the opening wireframe represents the converted geometry, not a native panel export. Side/front/top, rotation, zoom and Fit remain available. Successful preview conversion is reused by Save and Run.

Conditions defaults the editable moment reference to the incoming takeoff CG using the shared Weight & Balance loading summary. The launcher passes only the derived X/Y/Z coordinates alongside geometry. Older files with only Weight.CG_TO use that X and centerline Y/Z = 0; missing CG requires manual entry. Loading saved results or restoring a submitted case preserves its original reference.

Run VSPAERO automatically generates VSP3 if necessary, checks the selected service,
then submits the converted aircraft with the displayed conditions. Save .vsp3
reuses the opening conversion (or converts on demand) and asks for a destination before saving; it does not require analysis or a local/cloud solver. Save .vsp3 to cloud converts on demand and writes to Team Files / OpenVSP. The former JET2VSP widget is removed from default and restored layouts; its shared conversion core remains available for compatibility.

Aerodynamic, loads, stability, unsteady and propulsion runs use a separate, coarser
lifting-surface representation. **Span / axial mesh divisions** sets its section
budget per lifting component (default 15). The reducer retains root, tip and
explicit panel boundaries, then selects the sections with the largest sampled
skin error. Boundaries are kept even if their count exceeds the budget. Components
with fewer source sections retain those sections. Existing
chordwise and wake settings still control the native analysis mesh and wake.

The detailed blue preview and **Save .vsp3** keep the full geometry; aircraft JSON
is unchanged. The submitted analysis VSP3, pending-job checkpoint and native job
artifacts contain the reduced representation. Saved analysis report notes record
source/analysis section counts and maximum sampled skin deviation in feet.
Increase the span budget and compare results for mesh convergence; reduced
geometry is an approximation, not a proven accuracy bound. Wave drag, parasite
drag, mass properties and design studies retain the detailed geometry. Existing
pending submissions and restored saved results are not regenerated automatically.
This browser-side reduction works with the existing cloud worker and local helper;
it does not increase execution timeouts or change server resource limits.

## Helper downloads and run location

The visible Execution service selector applies to VSPAERO and every Additional Native
Analysis. Cloud VPS is first and selected by default, including when reopening a
completed case. Local computer remains an explicit alternate. Active or pending
restored jobs retain their saved run location so status, retry and cancellation
reach the service that owns the job. Switching location clears the previous
service capability check.
A spinning hourglass with “Computing in cloud…” stays visible at the top right
while cloud work is active, including submitted jobs and sweeps. It clears when
the active operation finishes or is cancelled; uncertain submitted jobs retain
the indicator until their status is resolved. Reduced-motion preferences keep
the hourglass visible without rotation.

Cloud execution requires deployment and website gateway configuration; selecting
Cloud VPS does not install its service.

Compute > Download Helper opens the same Windows, Mac and Python chooser as
Lattice. Each link asks where to save before fetching the package. Cancelling
saves nothing. Native Save As is used when available. Safari uses the shared confirmation/Save file flow; configure Safari to ask for each download. Browser handoff does not verify a disk save.

- Windows: extract JETcentral-OpenVSP-Helper-Windows.zip, open start-openvsp-helper-windows.cmd and choose the installed vsp.exe.
  The ZIP includes portable Python; OpenVSP is installed separately.
- Mac: install Python 3.10+, extract the Mac ZIP and open
  start-openvsp-helper-mac.command. Choose the extracted OpenVSP folder.
  Alternatively run `bash start-openvsp-helper-mac.command` in Terminal.
- Python: install Python 3.10+, extract the Python ZIP and run its server:

```sh
python openvsp-server.py --vsp "C:/path/to/OpenVSP/vsp.exe" --allow-origin https://www.jetdesign.online
```

Use the native `vsp` path on Mac/Linux. No additional Python packages are needed.
Download OpenVSP from https://openvsp.org/download.php and retain its accompanying
VSPAERO files. All three packages include openvsp-README.txt with instructions.
The Windows package uses the pinned, checksum-verified FEAHelper Python runtime.
Rebuild portable ZIP packages with `node JETcentral/scripts/package-openvsp-helper.mjs`. Windows also rebuilds the optional legacy EXE; Linux retains that EXE unchanged and the download chooser uses the updated Windows ZIP.
The Mac launcher is packaged executable, but requires validation on a Mac.

Launchers enable https://jetdesign.online, https://www.jetdesign.online and local
preview port 8767. Pass --allow-origin for a different exact website origin.
The helper binds 127.0.0.1:8773. Keep its window open and allow browser local-network
access when prompted. Select Local computer in Compute. An unreachable helper
opens setup instructions and leaves the case editable so it can be retried.

## Cloud setup

The native cloud service uses openvsp-server.py, openvsp-worker.py,
openvsp-engine.py, openvsp-analyses.py and fea-cloud-server.py. The existing FEA HTTPS site hosts its
/openvsp route. The installer is scripts/install-openvsp-vps.sh. From Windows,
scripts/deploy-openvsp-cloud.ps1 uploads and installs the service, retrieves private
settings, verifies authenticated HTTPS health and merges website configuration.
Use -RetryInstall to retry an uploaded installer, or -Resume to retrieve and verify
settings after installation. Diagnostic output is in _dev-scratch/openvsp-vps-install.log.
Do not publish private settings or tokens. CLOUD/config.example.php documents
openvsp_endpoint and openvsp_token; the website gateway keeps the service token
server-side. Local and cloud jobs require an owner session and idempotency key.

No successful cloud deployment is assumed by this document. A healthy endpoint
must report available=true and identify OpenVSP / VSPAERO before use.

## Model and result scope

The integration retains the JET2VSP document template and samples common renderer
geometry into native editable cross sections. The main wing retains its section
breaks, projected spans and airfoils; compatible wing/strake combinations export
as one blended wing, including the curved Designer leading edge. Detached strakes
remain separate. Tails, winglets and dorsal tails retain common coordinates,
cant and mirroring. Disabled components are omitted. Native wing summary values
are recomputed to prevent OpenVSP from rescaling the imported sections.

Fuselage profiles come from the common renderer's refined contours, including
non-elliptical sections, with their actual station coordinates. The old final
station compression to 97% of fuselage length is removed. The opening preview
meshes these same exported profiles. OpenVSP interpolates the sampled profiles;
its airfoil and fuselage interpolation can differ slightly between stations.
The implementation uses native [file airfoils and file fuselage sections](https://openvsp.org/api_docs/3.55.0/group___x_sec.html).

Detailed inlet ducts, engine bodies, arbitrary parts and control deflections are
not reproduced. External tanks remain explicitly unsupported. This is a closer
native parametric representation, not an exact common-renderer solid or a claim
that analysis includes inlet cutouts. Inspect the exported VSP3 before relying
on loads. Converted geometry must fit the existing 8 MB case limit.

Area, span and MAC default from the incoming main wing. Coordinates are feet,
X aft, Y right and Z up. Sweep angle ranges accept alpha/beta between -30 and 30 degrees,
Mach 0.01–3.0 and wake iterations 1–30. Aerodynamic runs exclude 0.95 < Mach < 1.05. Mach conversion uses standard-atmosphere sound speed at the entered altitude. VSPAERO potential-flow drag is not complete viscous/parasite drag.
Assess flow assumptions, geometry, discretization and wake convergence.

Completed coefficients, loads and plotted samples return to the opening Main
aircraft under `OpenVSP` through an aircraft-bound host transaction. Save results
exports aircraft JSON locally with Save As, or under Team Files / OpenVSP / Results.
The dictionary includes execution references and plot presentation, excluding VSP3,
solver logs, native decks and wake history. Reopening or loading this JSON restores
plots without running VSPAERO. Older standalone result bundles remain readable.
The six curves use bundled Plotly: drag or scroll to zoom, use the mode bar to pan
or reset, and drag formula annotations or legends. Saved plot state retains zoom,
annotation positions, the Cn alpha slice and the selected coefficient/load display. Submitted cases checkpoint their
run location and job state; reconnect using Check submitted job. Unknown submission
responses retain the idempotency key to avoid duplicate jobs on retry. Cancel job
requests service cancellation. Native job files expire after six hours; save results
for long-term retention. Inspect each job's openvsp.log for native failures.

OpenVSP and VSPAERO are separately installed NASA software, retain their upstream
licenses and are not bundled with the helpers. This integration does not imply
NASA endorsement. Native Windows execution has been tested with OpenVSP 3.55.0.

Ubuntu 22.04 deployment pins official OpenVSP 3.40.1 because newer 22.04 packages require libstdc++ 13.1, beyond the standard VPS runtime. This version uses the lifting-surface VLM fallback (fuselage and nacelle bodies excluded from analysis). Newer local installations support mixed thin/thick geometry. Native inputs are verified at their written decimal precision; dimensional loads use the actual native reference dimensions, airspeed and density. Interrupted package downloads resume and retry with TLS verification enabled. Unrelated pending Hestia errors are tolerated only after every requested dependency is configured.


## Speeds and analysis modes

Conditions > Speeds is above Sweep and More. Both analysis modes use the Liftoff
and Cruise speeds and their respective altitudes. Incoming JSON supplies a solved
STTO speed, or an estimate from takeoff weight, area, CLmaxTO and V/Vstall; missing
liftoff data requires manual entry. Cruise uses its JSON constraint or Mach 0.80.
Each speed uses standard-atmosphere density and sound speed at its own altitude.
The separate Airspeed/Mach, Alpha and Beta fields have been removed. More retains
reference dimensions and moment reference; its density readout is the derived
liftoff density.

Single condition runs two cases at the alpha and beta entered under More > Aerodynamic model and single-condition controls, once at each speed.
Parameter Sweep uses editable alpha start/end/step and beta start/end/step in the
Sweep subpanel. Defaults remain alpha -10 to 24 deg in 2 deg steps and beta -5 to
5 deg in 5 deg steps (108 cases total). Both ranges must contain a whole number
of positive steps; limits are -30 to 30 deg and 2000 total cases. Single condition
disables the Sweep entries without discarding them.

The native adapter generates matching point counts and endpoints for each speed,
verifies every returned coordinate, and computes Cn beta from the selected beta
endpoints divided by their separation in radians. A single beta does not produce
Cn beta. Plots use the actual alpha range and beta values; isolated single-condition
points are visible markers. Dynamic pressure/reference dimensions control the
optional lbf and ft·lbf display. Failed cases retain their coordinates and create
gaps. Labels remain draggable and saved with results. Saved default 1-deg and
2-deg sweeps, new custom sweeps and two-speed single conditions all reload without
running analysis.

Updated helpers/services advertise `parameterSweep: true`. Older services may
still run the unchanged 108-case default grid; edited grids and two-speed single
conditions require the new capability. Local helper downloads include the updated
engine. Updating the remote cloud service requires deployment authorization. Each
native batch retains its 30-minute bound and the service its 120-minute limit.
Potential-flow analysis is not a complete separated-flow or viscous/transonic drag model. The optional native stall model is explicitly selectable when supported; it does not make the method shock-resolving CFD.

## Optional authorized temporary SSH access

`setup-temporary-vps-ssh.ps1` installs a previously prepared Ed25519 public key with an explicit `expiry-time` on the VPS. Preparing a grant requires `-PrepareOnly -ExpiresAtUtc` with an authorized absolute UTC timestamp no more than 24 hours ahead. Installation cannot extend that timestamp. The user enters the VPS password once in PowerShell; it is neither read by the application nor saved. Existing authorized keys and password login are preserved. A unique backup of authorized_keys is kept on the VPS before adding or repairing this entry. For OpenSSH 8.9 compatibility, the fixed UTC deadline is rendered in server-local time without a timezone suffix; repairing the original UTC-suffixed entry never extends its deadline.

The private key and grant metadata remain under `%LOCALAPPDATA%/JETcentral/SSH/<host>/`, outside OneDrive, the repository and website packages, with access limited to the current Windows account and SYSTEM. The key is restricted against forwarding and user rc scripts, while permitting the terminal mode used by deployment. Both server expiry and the local grant check reject new connections after expiry; connection multiplexing is disabled. Existing SSH sessions do not acquire a longer grant. Deployment scripts select this key only for the matching root/host grant after installation is verified; otherwise their normal interactive authentication remains available.

Run the prepared installation once:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File ".\JETcentral\scripts\setup-temporary-vps-ssh.ps1"
```

The temporary key uses the official OpenSSH [authorized_keys restrictions and expiry](https://man.openbsd.org/OpenBSD-7.4/sshd). A future grant requires new user authorization; rerunning installation never extends an existing grant.

Edited grids and two-speed single conditions require an execution service/helper advertising parameterSweep. Older saved 1-degree (210-point) and default 2-degree (108-point) results remain loadable. Repackage and reinstall local helpers or update/restart the cloud service after this change.


Analysis curves include CL, CD and Cm versus alpha; Cn beta versus alpha; a CD-versus-CL drag polar; and Cn versus beta at the selected alpha (default zero, or the available alpha nearest zero). The alpha selector and coefficient/force display choices survive result save/reload. Angular axes use 1° ticks and twice the previous vertical grid density; coefficient-axis grid density is doubled as well. Both zero axes remain black.

Checkboxes below each graph enable its datasets. Each graph computes one least-squares fit over all finite enabled samples across the full sampled domain: linear for lift, pitching moment, Cnβ and Cn; quadratic for CD versus alpha and the CD(CL) drag polar. The movable boxed inset shows the equation using the corresponding aerodynamic variables, sample count and fit domain. The legend defaults to a movable box at the bottom inside the plot. Missing or insufficient samples show an unavailable fit instead of fabricated parameters. Dimensional plots fit the displayed force/moment values; saved Lift/Drag models always use coefficient fits.

Save to Lift/Drag Model takes CLa and zero-lift alpha from the enabled CL(alpha) fit and CDo/K1/K2 from the enabled drag-polar fit. Enabled selections are retained in optional version-1 `OpenVSP.plots.fitSelection`; the saved source records exact fitted domains, selected conditions and fit coefficients. Changing a checkbox affects fit inputs; moving a legend/inset, zooming or changing display units does not change coefficient fits or source identity. Empty, singular, nonpositive lift-slope or nonphysical drag-polar fits remain unavailable. A source may contain only the usable lift or drag fit; all-unavailable saves are refused atomically. Distinct selected Mach/sideslip conditions are recorded as a pooled empirical fit, never relabeled as a single native execution condition. No stall CLmax is inferred.

Each Analysis curves plot has its own Save Plot button. It opens Save As (PNG by default, with JPG/SVG also supported by the shared exporter). Export includes only that plot at its current units/alpha slice, with legend, black zero axes, grids and dragged annotation positions; raster output is 2× resolution. Cancellation writes nothing; unsupported browsers show the existing Edge/Chrome message rather than downloading silently.

Plot default and reset ranges use a conservative outer-IQR filter per curve so isolated
extreme samples do not compress the useful data. Coefficients, fits, traces and saved
samples remain unchanged. Separate curves retain their own scale during range selection.
Manual zoom/pan can reveal samples outside the default view. Earlier saved axis ranges
are refreshed once when adopting this range policy; annotations and legends are retained.

## Additional native analyses (contract 3, result schema 2)

Conditions > More > Aerodynamic model and single-condition controls exposes mesh,
Reynolds number, wake nodes, fixed/implicit wake, native stall/CLmax and thin/mixed/thick
surface selection. Automatic mode uses thin surfaces for supersonic VSPAERO.
Additional native analyses is a separate collapsible section above Compute:

| Action | Inputs and result |
| --- | --- |
| Loads and pressure | Cruise condition, selected X/Y/Z cut; spanwise loads and Cp/delta-Cp slice |
| Stability derivatives | Cruise condition; finite differences or supported native adjoint derivatives |
| Unsteady response | Roll/pitch/yaw perturbation; actual native time history (solver chooses perturbation time grid) |
| Propulsion interaction | One analysis-only propeller, actuator disk CT/CP or generic rotating blades; position/orientation, RPM, diameter and blade count; blade mode accepts time grid |
| Supersonic wave drag | Separate Mach > 1, axial slices/cone sections, symmetry; area-rule CD and area distribution |
| Parasite drag | Cruise altitude/speed, laminar fraction, interference Q, separate added excrescence; recomputed converted wetted areas |
| Mass, CG and inertia | Equivalent shell/volume weight densities, exact-name component overrides/overlap priority and assigned point masses; slug/ft/lbf units |
| Automated design study | Sample main-wing span/sweep/taper/twist bounds; choose maximum L/D or minimum CD subject to minimum CL; fixed reference dimensions |

Each completed run keeps its own conditions, options, report and plot state under
`OpenVSP.analyses`. Switching saved runs never invokes a solver. Save results JSON
retains the aircraft and all completed analyses; schema 1 saved results still open.
CSV and plot PNG exports ask for Save As. The native-viewer ZIP includes retained
VSP3/ADB and associated files from the selected completed job; these remain outside
aircraft JSON and expire with that job. Reloaded JSON does not claim native files
are still available. Cancelling or closing the page rejects late job responses.

These tools do not modify aircraft geometry, JET Weight Model results or official
performance equations. The design study saves its best native VSP3 for inspection;
it does not automatically apply a sampled design to Main. Mass properties are
independent of JETcentral's component-mass model. Propellers use analysis geometry,
not a detailed imported blade design. Wave drag is separate to avoid double-counting;
flow-through inlet/exhaust faces are unavailable. Review mesh/wake/time convergence:
the test aircraft failed natively at a 5-by-9 mesh but passed at the normal 15-by-17
mesh for steady runs. Full-aircraft unsteady runs require a finer mesh (21-by-25 in verification); the native coarse-grid agglomeration can fail on intersecting wing/strake geometry. Failed native runs are errors, never fabricated coefficients.

An updated helper/service must advertise `analysisSuite` and its detected native
version/capabilities. OpenVSP 3.55.0 is recommended. Older installations disable
unavailable functions; selecting Cloud VPS does not update the service. Website
files alone cannot install these server-side Python changes. Use the documented
deployment process to update/restart the service separately. Existing-site website
packages omit helpers by default; explicitly include updated helpers when installing the native analysis suite
for the first time, or upload its three helper ZIPs separately.

Verification commands (from repository root):

```sh
npm --prefix JETcentral run build
npm --prefix JETcentral test
npm --prefix JETcentral run test:browser:openvsp-execution
OPENVSP_EXE=/path/to/vsp npm --prefix JETcentral run test:browser:openvsp-analyses
OPENVSP_EXE=/path/to/vsp npm --prefix JETcentral run test:openvsp:packages
```

The execution browser check captures submissions for all eight additional actions on
both cloud and local routes, checks capability switching and restored job ownership,
and does not require OpenVSP. The analyses browser test uses real OpenVSP/VSPAERO,
checks every additional action, independent
reports, CSV/native exports, plot dragging, JSON reload and cancellation. Package
checks compare every shipped Python source, verify the pinned Windows runtime bytes
and Mac executable permission, and start each extracted helper. On Windows they use
the bundled Python; elsewhere they use installed Python for source smoke checks.
Mac GUI launcher/Safari and Windows runtime execution require those platforms and
are not established by Linux archive checks. No live VPS deployment is implied.

## Supersonic wave-drag Mach sweep

In Additional native analyses → Supersonic wave drag, **Low Mach** and **High Mach**
default to 1 and 2. The browser creates exactly ten evenly spaced rows, including
both endpoints; supported limits are `1 ≤ low < high ≤ 3`. Range values and mesh,
reference area, symmetry, alpha/beta and geometry are captured at Run. Every valid
supersonic row is an ordinary native `wave-drag` job on the selected Cloud VPS or
Local computer service. This browser orchestration uses the existing analysis-suite
protocol; no VPS Python or helper-download update is needed for this feature.

Mach 1 is sonic, outside the native supersonic wave-drag method. Its row remains
explicitly unavailable and is never silently moved to another Mach or assigned zero.
The default range consequently has nine native evaluations and one sonic-boundary
row. Starting above Mach 1 produces ten native evaluations. Failed native points
also remain unavailable; the sweep continues with the remaining points. A completely
failed sweep reports that no native Mach points completed rather than inventing CD.

Saved native analyses show a ten-row Mach/CDWave/status table and a **CDwave versus
Mach** plot spanning the entered limits. Missing values form gaps; they are not
connected across failed points. The final native cone-section area distribution is
retained separately. Native viewer files belong to the last successful Mach, stated
in the report, not to all ten samples. Each Mach uses the same converted geometry
and reference area; wave drag is kept separate from other drag estimates.

The sequence respects the existing five-submission service window. A 429 response
retains the same request ID and retries after a cooldown. Status identifies the active
Mach. Cancel stops further submissions, requests cancellation of the active native
job, and rejects late responses. The private page checkpoint retains completed rows,
the active job and pending request; reload and Check submitted job continue that
sequence without recalculating its completed rows. A cancelled or incomplete sweep
never replaces the previous completed aircraft report.

Completed tables, limits and label positions survive JSON save/reload through the
existing schema-2 OpenVSP dictionary. Older single-Mach wave reports remain readable;
new sweep controls initially use Mach 1–2. Selecting saved reports does not submit
jobs. CSV includes all ten rows. Plot labels remain draggable and bounded; plot
PNG/JPEG/SVG exports use Save As and reject a changed/disposed result. Browser-only
fallback delivery is reported as a handoff, not a verified disk save.

Verification:

```sh
node --test JETcentral/tests/openvsp-wave-sweep.test.mjs JETcentral/tests/openvsp-analyses.test.mjs
npm --prefix JETcentral run test:browser:openvsp-wave-sweep
OPENVSP_EXE=/path/to/vspscript npm --prefix JETcentral run test:browser:openvsp-wave-sweep
```

The browser fixture checks range validation, ten rows, failed-point gaps, plots,
CSV/JSON saves, label movement, no-run restore, rate retry, checkpoint resume and
late completion after Cancel. With OPENVSP_EXE it uses the real local helper and
native OpenVSP for all nine valid points of the default range. Existing native
analysis routing checks continue to cover cloud and local execution.


## Browser pressure and wake viewer

The OpenVSP page includes a separate **Pressure and wake viewer** below the setup
workspace. After a completed run, select Liftoff or Cruise, select a native
alpha/beta case, and click **Load selected case**. The viewer reads actual native
ADB results; it does not estimate surface pressures from aircraft coefficients.
Toggle pressure colors, orange wake lines and panel edges independently. Drag to
rotate, scroll to zoom, use the toolbar to pan, or choose Side, Front, Top or Fit.
The wake display extent clips far-field lines around the aircraft without changing
saved native coordinates. The pressure color bar can be dragged.

Supported binary layouts are the official OpenVSP 3.40.1 and 3.55.0 steady,
full-aircraft JET cases. VLM pressure is delta-Cp on thin lifting surfaces; mixed
runs contain Cp on thick surfaces and delta-Cp on thin surfaces. Newer solver wake
triangles are separated from pressure-colored aircraft triangles and displayed as
wake mesh edges. Legacy wake filaments are drawn from their native coordinates.
Unsupported, truncated or nonfinite native files leave coefficient results usable
and report that viewer data is unavailable.

**Save viewer JSON** asks for a destination and saves the displayed native case,
including its mesh, pressure values, full wake coordinates, camera and color-bar
position. **Load viewer JSON** restores it without a solver. Save each desired
case before native job files expire after six hours. Aircraft result JSON remains
the compact coefficient/curve format; it does not embed these large native arrays.
The page checkpoint retains its original job and execution location for reconnects.

The helper/service must include `openvsp-viewer.py`; health advertises
`pressureWakeViewer: true`. The Windows, Mac and Python helper packages include it.
Cloud deployment source manifests also include the reader; a remote service update
is needed before new cloud runs return viewer case metadata. Existing services and
older saved coefficient results remain usable without pressure/wake data. Per-case
requests pass through the existing owner-authenticated gateway; job IDs do not
grant access to another session's results.

Validation: `python JETcentral/tests/test_openvsp_viewer.py`,
`node --test JETcentral/tests/openvsp-solution-view.test.mjs`, and
`node JETcentral/scripts/check-instance-startup.cjs check-openvsp-solution-view.cjs`.
Set `OPENVSP_VIEWER_FIXTURE` to a native viewer JSON to exercise real geometry in
the browser check; otherwise it uses a small explicit fixture.
