kshana 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,40 +6,49 @@
6
6
 
7
7
  <p align="center">
8
8
  <strong>क्षण</strong> — Sanskrit for <em>the precise instant</em>, the smallest measure of time.<br>
9
- Open, reproducible hybrid quantum / classical PNT performance simulation.
9
+ Open, reproducible PNT-resilience simulation with published quantum-sensor performance models.
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- <a href="https://ashfordeou.github.io/kshana/"><img src="https://img.shields.io/badge/playground-try%20in%20browser-2dd4bf" alt="Live playground — run in your browser, no install"></a>
13
+ <a href="https://ashfordeou.github.io/kshana/"><img src="https://img.shields.io/badge/playground-try%20in%20browser-c79e63" alt="Live playground — run in your browser, no install"></a>
14
14
  <a href="tests/sgp4_verification.rs"><img src="https://img.shields.io/badge/SGP4-666%2F666%20AIAA%20vectors%20%C2%B7%204.12mm-3fb950" alt="SGP4 validated against all 666 AIAA 2006-6753 vectors, worst 4.12 mm"></a>
15
15
  <a href="https://github.com/ashfordeOU/kshana/actions/workflows/ci.yml"><img src="https://github.com/ashfordeOU/kshana/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
16
16
  <a href="https://github.com/ashfordeOU/kshana/releases"><img src="https://img.shields.io/github/v/release/ashfordeOU/kshana?sort=semver" alt="Release"></a>
17
17
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License: Apache-2.0"></a>
18
18
  <a href="Cargo.toml"><img src="https://img.shields.io/badge/rust-1.75%2B-orange.svg" alt="Rust 1.75+"></a>
19
+ <a href="https://doi.org/10.5281/zenodo.20528627"><img src="https://zenodo.org/badge/1256508460.svg" alt="DOI"></a>
19
20
  </p>
20
21
 
21
22
  <p align="center">
22
23
  <strong>Kshana</strong> (क्षण, Sanskrit: <em>"the precise instant"</em>) is an open, reproducible
23
24
  <strong>PNT-resilience simulator with quantum-sensor performance models</strong> —
24
- positioning, navigation, and timing. It compares quantum and classical sensors using
25
- published Allan/noise-budget coefficients; it is not a first-principles quantum-physics
26
- simulator (see <a href="docs/QUANTUM-MODELS.md">docs/QUANTUM-MODELS.md</a>).
25
+ positioning, navigation, and timing. It compares quantum and classical sensors mostly
26
+ from published Allan/noise-budget coefficients, with a first-principles cold-atom-
27
+ interferometer accelerometer layer (Mach–Zehnder phase, quantum projection noise,
28
+ contrast decay, and vibration coupling) that <em>derives</em> the noise coefficient
29
+ rather than looking it up; it is not yet a full quantum-physics simulator (Coriolis and
30
+ light-shift systematics remain coefficient-level — see
31
+ <a href="docs/QUANTUM.md">docs/QUANTUM.md</a> and
32
+ <a href="docs/QUANTUM-MODELS.md">docs/QUANTUM-MODELS.md</a>).
27
33
  </p>
28
34
 
29
35
  It quantifies, in hard and reproducible numbers, what quantum clocks, quantum
30
36
  inertial sensors, and optical time-transfer buy a navigation system over classical
31
37
  PNT — scored against the operational figures of merit that matter for resilient
32
38
  navigation. Every result is reproducible from `scenario + seed + engine version`,
33
- and every sensor parameter is traceable to a published source.
39
+ and every sensor parameter is traceable to a published source — consolidated in one
40
+ citable table in [`docs/PROVENANCE.md`](docs/PROVENANCE.md).
34
41
 
35
42
  *Free and open source under Apache-2.0, professionally developed and maintained by
36
43
  Ashforde OÜ — commercial support, integration, and proprietary extensions available.*
37
44
 
38
- > **Status: v0.9.2 · a simulation substrate, not yet a product.** A validated,
39
- > fully reproducible engine spanning the PNT stack — orbit geometry, inertial
40
- > navigation, GNSS/INS fusion, integrity, clocks, and timing. Honest by design:
41
- > every figure of merit is labelled *validated* or *not-modeled*, and optical-clock
42
- > figures are space goals on ground hardware (no strontium optical clock has flown).
45
+ > **Status: v0.11.0 · a simulation substrate, not yet a product.** A validated,
46
+ > fully reproducible engine spanning the PNT stack — orbit geometry and constellation
47
+ > design, time systems, inertial navigation (incl. map-aided), GNSS/INS fusion (loose,
48
+ > tight, UKF, coupled clock+position), ARAIM integrity, clocks, advanced time-and-frequency
49
+ > transfer, the GNSS measurement domain, and resilience (jamming + multi-layer spoofing).
50
+ > Honest by design: every figure of merit is labelled *validated* or *not-modeled*, and
51
+ > optical-clock figures are space goals on ground hardware (no strontium optical clock has flown).
43
52
  > See **[Capabilities](#capabilities)** for what it does, **[What it is / is not](#what-it-is--is-not)**
44
53
  > for scope, and [`docs/CAPABILITY.md`](docs/CAPABILITY.md) / [`docs/VALIDATION.md`](docs/VALIDATION.md)
45
54
  > for per-capability maturity and the claims table.
@@ -96,17 +105,30 @@ receiver, or a certified avionics product. Quantum-hardware fidelity comes from
96
105
  published error models, not from this tool. The granular maturity of each
97
106
  capability is documented in [`docs/CAPABILITY.md`](docs/CAPABILITY.md).
98
107
 
108
+ **It is not (yet):** a *full* atom-interferometry physics engine (most quantum sensors
109
+ consume published Allan/noise-budget coefficients; the CAI accelerometer has a
110
+ first-principles layer — Mach–Zehnder phase, projection noise, contrast decay, and
111
+ vibration coupling — but Coriolis and light-shift systematics remain a **P2** roadmap
112
+ layer, see [`ROADMAP.md`](ROADMAP.md) and [`docs/QUANTUM-MODELS.md`](docs/QUANTUM-MODELS.md));
113
+ a GNSS receiver or PVT solver (it models the measurement domain and resilience, not
114
+ signal acquisition or a least-squares fix); or a mission-design / orbit-determination
115
+ tool. Owning this scope is deliberate. If you need first-principles cold-atom
116
+ interferometer error budgets (e.g. CARIOQA-PMP-grade or X-37B-style validation), see
117
+ the P2 roadmap and [get in touch](#support--professional-services) to collaborate.
118
+
99
119
  ## Capabilities
100
120
 
101
121
  | Domain | Capability |
102
122
  |--------|------------|
103
- | **Orbit & geometry** | SGP4/SDP4 propagation (validated to 4.12 mm against all 666 AIAA 2006-6753 vectors), real-TLE or synthetic Walker constellations, multi-constellation visibility, dilution of precision, and GNSS availability. |
104
- | **Inertial** | Three-axis strapdown INS quaternion attitude, WGS-84 NED mechanization, coning/sculling compensation, and a deterministic IMU error model (scale-factor, misalignment, g-sensitivity, quantization, drift). |
105
- | **Fusion** | Loosely-coupled GNSS/INS error-state EKF (15-state) with closed-loop feedback that coasts through GNSS outages on a calibrated inertial solution. |
106
- | **Integrity** | Snapshot and solution-separation (ARAIM-style) RAIM with horizontal/vertical protection levels (HPL/VPL), fault detection and identification, and Stanford integrity diagrams. |
107
- | **Clock & timing** | Two-state Kalman holdover, Allan-family stability (ADEV/MDEV/TDEV/HDEV) with confidence intervals, and optical/RF two-way time transfer. |
108
- | **Interoperability** | RINEX-3 GPS broadcast-ephemeris ingestion with IS-GPS-200 satellite position and clock evaluation. |
109
- | **Resilience** | Clock-aided spoof-detectability analysis against a configurable time-spoof attack. |
123
+ | **Orbit & geometry** | SGP4/SDP4 propagation (validated to 4.12 mm against all 666 AIAA 2006-6753 vectors); real two-line elements (a committed, date-stamped Celestrak `gps-ops` snapshot) or synthetic Walker-delta constellations whose mean elements realise the `i:T/P/F` formula to under 1 km over a 24 h propagation; multi-constellation visibility, dilution of precision, and GNSS availability; a gradient-free constellation-design optimiser, streets-of-coverage minimum-satellite sizing, a multi-constellation comparison tool, and a Walker **design sweep** that tabulates coverage / PDOP / revisit-time over a planes × satellites grid and reports the Pareto-optimal designs. |
124
+ | **Time systems** | IERS leap-second **UTC / TAI / TT / UT1** scales, a Julian-date API, the IAU-2000 **Earth Rotation Angle**, and GMST-based **TEME ↔ ECEF** with WGS-84 geodetic frames — plus IAU 2006 precession (Fukushima–Williams) toward an ITRF-precise reduction. |
125
+ | **Inertial** | Three-axis strapdown INS — quaternion attitude, WGS-84 NED mechanization, coning/sculling compensation, and a deterministic IMU error model (scale-factor, misalignment, g-sensitivity, quantization, drift); a **first-principles cold-atom-interferometer accelerometer** (Mach–Zehnder phase, quantum projection noise, contrast decay, vibration coupling) that *derives* the velocity-random-walk coefficient; and a sequential-importance-resampling **particle filter** for map-aided (terrain-/gravity-referenced) GPS-denied navigation. |
126
+ | **Fusion** | Loosely-coupled 15-state GNSS/INS error-state EKF with closed-loop feedback (the `gnss-ins` pack); a **tightly-coupled** pseudorange update that keeps correcting with fewer than four satellites; a coupled **clock + position** filter; a general **unscented (sigma-point) Kalman** estimator for strongly nonlinear measurements; and a tightly-coupled GNSS/INS **UKF navigator** (pseudorange + Doppler) whose force-model orbital coast is validated to **0.77 m RMS** over a 30-minute curving LEO pass that includes a 120-second GNSS outage. |
127
+ | **Integrity** | Snapshot and solution-separation (ARAIM-style) RAIM with horizontal/vertical protection levels (HPL/VPL), fault detection & exclusion, and Stanford integrity diagrams; an explicit integrity-risk-budget (**MHSS**) protection level, including the **dual-/multi-constellation constellation-wide fault mode** (EU ARAIM / DO-316). |
128
+ | **Clock & timing** | Two-state Kalman holdover (Joseph-form covariance, NIS/NEES consistency health); Allan-family stability (ADEV / MDEV / TDEV / HDEV) with noise-type-specific confidence intervals and a full **IEEE-1139 five-coefficient power-law fit**; geometric corrections (Sagnac, GNSS common-view); and the operational transfer methods — **TWSTFT** with the BIPM Sagnac closed form, **GNSS common-view**, **PPP** ionosphere-free time transfer, a free-space **optical** link with turbulence scintillation, and an inverse-variance **clock-ensemble (paper) timescale** below the best contributing clock. |
129
+ | **GNSS measurement domain** | Forward pseudorange / Doppler synthesis with **Klobuchar** (broadcast) and **IONEX / TEC-grid** (measured) ionosphere including an IONEX file parser, time interpolation between maps, and the thin-shell slant-obliquity mapping — **Saastamoinen + Niell** troposphere, and snapshot RAIM (HPL/VPL). |
130
+ | **Resilience** | Link-budget **jamming** (J/S → effective C/N₀ → loss of lock); a stochastic **time-spoof detector** (Neyman–Pearson / χ²₁ energy test with closed-form and Monte-Carlo P_fa/P_md and a Security FoM of 1 − P_md); and a **multi-layer spoof detector** fusing a RAIM-consistency parity test (with the common-mode blind spot modelled honestly), an RF AGC-power monitor, and a signal-quality (SQM early-minus-late) monitor. |
131
+ | **Interoperability** | **RINEX-3** multi-GNSS broadcast-ephemeris ingestion (GPS, Galileo, QZSS, BeiDou MEO/IGSO via IS-GPS-200; GLONASS via PZ-90 state-vector RK4) usable as a constellation source (RINEX in, PNT geometry out); a **RINEX-3/4** observation parser (pseudorange, carrier phase, Doppler, signal strength); an **SP3-c/d** precise-ephemeris reader/writer with 9th-order Lagrange interpolation; and **CCSDS OEM 2.0 + OMM** (mean-elements) export for flight-dynamics tools (GMAT, Orekit, STK). |
110
132
 
111
133
  Each capability is reachable as a Rust API, a runnable scenario `kind`, or both.
112
134
  Maturity per capability — *validated*, *runnable*, or *library* — is tracked in
@@ -147,9 +169,17 @@ The constellation can also be given as real two-line element sets. A *full* TLE
147
169
  (line 1 + line 2) is propagated with the full **SGP4/SDP4** model — including
148
170
  atmospheric drag and the deep-space lunar-solar and 12 h / 24 h resonance terms that
149
171
  matter for ~12 h GNSS orbits — validated against the official AIAA 2006-6753 vectors
150
- to a worst-case ≈ 4 mm (`scenarios/orbit-sgp4-gps.toml`). A line-2-only block keeps
172
+ to a worst-case ≈ 4 mm. `scenarios/orbit-sgp4-gps.toml` ships a **real Celestrak
173
+ `gps-ops` snapshot** of the operational GPS constellation (2021-07-28, 30 satellites)
174
+ and requires valid TLE checksums — two-line element sets are open data from the US
175
+ Space Force / 18th Space Defense Squadron catalogue, redistributed by Celestrak
176
+ (Dr T. S. Kelso, [celestrak.org](https://celestrak.org)); refresh with
177
+ `scripts/fetch_tles.sh`. A line-2-only block keeps
151
178
  the analytic two-body propagation (`scenarios/orbit-real-tle.toml`); the two forms can
152
- be mixed in one constellation.
179
+ be mixed in one constellation. A constellation can equally be built from a block of
180
+ **RINEX-3 GPS broadcast-ephemeris** records — the format a receiver decodes —
181
+ propagated by the IS-GPS-200 user algorithm and fed through the same geometry
182
+ (`scenarios/orbit-rinex.toml`).
153
183
 
154
184
  ## Install & build
155
185
 
@@ -174,9 +204,21 @@ cargo run -- scenarios/timetransfer.toml
174
204
  cargo run -- scenarios/hybrid-pnt.toml
175
205
  cargo run -- scenarios/orbit-gnss-challenged.toml
176
206
  cargo run -- scenarios/orbit-sgp4-gps.toml
207
+ cargo run -- scenarios/orbit-rinex.toml
177
208
  cargo run -- scenarios/integrity-raim.toml
209
+
210
+ # Export a propagated constellation to an SP3-c precise-ephemeris file:
211
+ cargo run -- scenarios/orbit-sgp4-gps.toml --export-sp3 gps.sp3
178
212
  ```
179
213
 
214
+ **Interoperability role.** Kshana is the *performance-simulation* layer that sits
215
+ alongside the post-processing toolchain, not a replacement for it: feed its **RINEX**
216
+ output into RTKLIB or gLAB for a position solution, and use its **SP3** output as a
217
+ precise-orbit product for tools like Ginan — Kshana answers *what resilience a given
218
+ PNT architecture buys* before you have real signals, in formats those tools already
219
+ ingest (`--export-sp3`, or `export_sp3 = true` in an `orbit` scenario, writes
220
+ `<scenario>.sp3`).
221
+
180
222
  Example output (clock holdover — note the Integrity and Security figures of merit):
181
223
 
182
224
  ```
@@ -245,8 +287,9 @@ console.log(version(), result.classical.fom.timing_p95_ns);
245
287
 
246
288
  ## Scenario format
247
289
 
248
- Scenarios are declarative TOML. A top-level `kind` selects the pack
249
- (`clock` is the default if omitted; `inertial`, `timetransfer`, `hybrid`, `orbit`).
290
+ Scenarios are declarative TOML. A top-level `kind` selects the pack (`clock` is
291
+ the default if omitted; `inertial`, `timetransfer`, `hybrid`, `fusion`,
292
+ `gnss-ins`, `orbit`, `gnss-sim`, `integrity`, `spoof`, `jamming`, `sweep`, `sweep-nd`).
250
293
  Common fields: `seed`, a `[time]` grid, a `[gnss]` availability timeline (the outage
251
294
  driver), and per-sensor blocks with `provenance` strings citing the source of every
252
295
  figure. Example (clock):
@@ -289,9 +332,13 @@ quaternion attitude with coning/sculling compensation, a full NED mechanization
289
332
  (Earth-rate and transport-rate terms, WGS-84 Somigliana gravity), and a
290
333
  deterministic IMU error model in which **scale-factor, misalignment,
291
334
  g-sensitivity, quantization, and rate-ramp are modelled** (IEEE Std 952-1997
292
- §A.2; Groves 2013 §4.3). That 3-axis path is **not yet wired into the scenario
293
- pack/FoM** switching the pack over, with a loosely-coupled GNSS/INS filter, is
294
- the next inertial milestone. A
335
+ §A.2; Groves 2013 §4.3). That 3-axis path is now **wired into a runnable
336
+ loosely-coupled GNSS/INS pack** (`kind = "gnss-ins"`): a 15-state error-state EKF
337
+ disciplines the strapdown solution against noisy fixes while GNSS is up, then
338
+ coasts through the outage, reporting the fused horizontal error against the
339
+ open-loop free-INS coast. A **tightly-coupled pseudorange** update is also
340
+ available (it forms the innovation in the range domain, so it keeps correcting
341
+ with fewer than four satellites). A
295
342
  clock-holdover scenario may add `runs` (> 1) to run a **Monte Carlo ensemble** — each
296
343
  figure of merit is then reported as a mean with a 5th–95th-percentile spread and the
297
344
  chart shades the error confidence band (see `scenarios/clock-ensemble.toml`).
@@ -303,10 +350,39 @@ cross-covariance: this is a stacked pair of error budgets, **not** a true couple
303
350
  clock+position joint filter (cross-block covariance is a roadmap item). See
304
351
  `scenarios/fusion-pnt.toml`.
305
352
 
306
- A `spoof` scenario injects a ramping false-time spoof (an `[attack]` block with
307
- `start_s` and `rate_ns_per_s`) and runs each clock's integrity monitor, reporting
308
- whether and when the spoof is detected and whether it reaches the spec undetected a
309
- concrete demonstration of the Security figure of merit (see `scenarios/spoof-attack.toml`).
353
+ A `spoof` scenario injects a time-spoof one of four `[attack.shape]` kinds
354
+ (`linear_ramp`, `step_jump`, `meaconing`, `replay`; a bare `rate_ns_per_s` is still
355
+ accepted as a linear ramp) and runs each clock's spoof detector. The detector is a
356
+ two-sided **χ²₁ energy / Neyman–Pearson test** on the clock-aided monitor statistic:
357
+ the threshold is set from a target false-alarm budget `target_pfa`, and the
358
+ **missed-detection probability `P_md`** is reported both closed-form and by
359
+ Monte-Carlo (`mc_runs` trials per hypothesis — the two agree to a few ×1/√N). The
360
+ **Security figure of merit is `1 − P_md`** at the operationally-harmful (spec)
361
+ magnitude, so a quiet clock that catches a spec-sized spoof scores ≈ 1 and a noisy
362
+ one that often misses it scores lower (see `scenarios/spoof-attack.toml`,
363
+ `scenarios/spoof-meaconing.toml`).
364
+
365
+ A `gnss-sim` scenario is a **measurement-domain** simulation: for each visible
366
+ satellite it synthesises the pseudorange `ρ = geometric range + c·δt_rx − c·δt_sv +
367
+ I + T + noise + multipath` and the L1 Doppler, with the **Klobuchar** single-frequency
368
+ ionosphere (`[iono]`, IS-GPS-200 §20.3.3.5.2.5) and the **Saastamoinen** zenith
369
+ troposphere projected by the **Niell (1996)** mapping function (`[tropo]`). The
370
+ residuals feed **snapshot RAIM** for per-epoch HPL/VPL, and every satellite's
371
+ pseudorange, Doppler, C/N₀, and iono/tropo corrections are emitted in the JSON
372
+ `gnss_measurements` array. It is a forward simulator (it generates measurements from
373
+ a known truth), not a receiver/solver — a zero-noise run reproduces geometry plus the
374
+ corrections to sub-millimetre (see `scenarios/gnss-sim-raim.toml`).
375
+
376
+ A `jamming` scenario models RF interference as a **link budget**: a `[jammer]`
377
+ (ECEF position, transmit `power_dbw`, type) raises the jammer-to-signal ratio at a
378
+ `[receiver]` watching a Walker `[constellation]`. From the geometry (free-space
379
+ path loss and the per-direction receive-antenna gain) it computes each satellite's
380
+ `J/S`, the **effective C/N₀** via the standard anti-jam equation (despreading
381
+ processing gain × the spectral-separation factor `Q`; Kaplan & Hegarty §9.4), and
382
+ flags loss of lock below a configurable tracking threshold — reporting an
383
+ `availability_under_jamming` figure of merit. A 10 W broadband jammer at 1 km
384
+ denies the receiver entirely (J/S ≈ 72 dB); the same jammer at 100 km only
385
+ degrades the links (see `scenarios/jamming-demo.toml`).
310
386
 
311
387
  A `sweep` scenario runs a **trade study**: it varies one `parameter` (`threshold_ns`,
312
388
  `duration_s`, `quantum_q_wf`, or `classical_q_wf`) from `start` to `stop` over `steps`
@@ -314,6 +390,14 @@ points on a `lin` or `log` `scale`, records a `metric` (e.g. `holdover_s`) for b
314
390
  clocks, and charts the two curves. The base scenario goes under `[base]` (see
315
391
  `scenarios/sweep-clock-stability.toml`).
316
392
 
393
+ A `sweep-nd` scenario generalises this to **any pack and any number of axes**: it
394
+ varies dotted TOML keys of a `[base]` scenario (of any `kind`) over the Cartesian
395
+ product of `[[axes]]`, re-runs each grid node, and records `metrics` given as
396
+ dotted JSON paths into the result (e.g. `classical.fom.holdover_s`). It works for
397
+ every pack because it operates at the TOML/result boundary; native runs evaluate
398
+ the grid in parallel (no extra dependency, wasm falls back to sequential) and the
399
+ output is deterministic and row-major (see `scenarios/sweep-nd-inertial.toml`).
400
+
317
401
  An `orbit` scenario derives the `[gnss]` timeline from geometry instead of authoring
318
402
  it — give a `[user]` orbit, a `[constellation]`, an elevation `mask_deg`, and the two
319
403
  clock blocks. It also reports position accuracy from the satellite geometry; the
@@ -355,10 +439,13 @@ See `scenarios/` for one example of every kind.
355
439
  The result artifact is versioned, self-describing JSON: per-step time series, the
356
440
  scored figures of merit, the active model specs (with provenance), the seed, a
357
441
  **scenario hash** — so any chart can be reproduced from the file — and, for each clock,
358
- an `adev_curve` (`[{tau_s, adev, n_samples}]`): the overlapping Allan deviation across
359
- octave-spaced averaging times, the standard way to read a clock's stability. The
360
- browser playground renders it as a log-log "Clock stability (ADEV)" chart. (MDEV/TDEV/HDEV
361
- and confidence intervals are not yet computed roadmap.) Every field, with units and a
442
+ an `adev_curve` (`[{tau_s, adev, n_samples, noise, edf, ci_lo, ci_hi}]`): the overlapping
443
+ Allan deviation across octave-spaced averaging times the standard way to read a clock's
444
+ stability now with a **noise-type-specific 95% confidence band** per point (the record's
445
+ power-law type is identified from its modified-Allan slope, and the χ² interval uses the
446
+ matching NIST SP 1065 effective degrees of freedom). The browser playground renders it as a
447
+ log-log "Clock stability (ADEV)" chart. (MDEV, TDEV, and HDEV are available as library
448
+ estimators; the exported result curve is the overlapping ADEV.) Every field, with units and a
362
449
  source pointer, is documented in [`docs/SCHEMA.md`](docs/SCHEMA.md). The figures of
363
450
  merit follow the standard operational PNT figures of merit:
364
451
 
@@ -462,6 +549,7 @@ kshana/
462
549
  | [Glossary](docs/GLOSSARY.md) | everyone | plain-language definitions of every term |
463
550
  | [Architecture](docs/ARCHITECTURE.md) | developers / reviewers | module map, engine pipeline, dispatch, and diagrams |
464
551
  | [Validation status](docs/VALIDATION.md) | reviewers / citers | what is `validated` vs `not modeled`, with evidence |
552
+ | [Provenance](docs/PROVENANCE.md) | reviewers / citers | every sensor parameter, model, and dataset traced to its published source, in one citable table |
465
553
  | [Reproducibility &amp; provenance](docs/REPRODUCIBILITY.md) | reviewers / packagers | determinism guarantees, golden-pinning, SBOM, build provenance |
466
554
  | [Positioning](docs/POSITIONING.md) | evaluators | where Kshana sits vs RTKLIB/gLAB (complementary), and the zero-install browser tier |
467
555
  | [SGP4 validation](docs/SGP4-VALIDATION.md) | reviewers / citers | agreement with the AIAA 2006-6753 reference (666 states, ~4 mm) |
@@ -537,15 +625,25 @@ CPython versions).
537
625
 
538
626
  ## Roadmap
539
627
 
540
- See [`CHANGELOG.md`](CHANGELOG.md) for released history and the `[Unreleased]`
541
- section for what's next (Earth-fixed frame reduction — TEME&rarr;ECEF/ITRF and
542
- explicit time systems: UTC/UT1/TAI/TT with leap seconds). SGP4/SDP4 orbit
543
- propagation has **shipped** (v0.7.0, validated against the AIAA 2006-6753 vectors),
544
- and its inertial velocity is now exposed downstream. An active
545
- spoofing-attack demonstrator, multi-constellation availability, a single-axis (1-DOF)
628
+ See [`ROADMAP.md`](ROADMAP.md) for the phased roadmap, [`CHANGELOG.md`](CHANGELOG.md)
629
+ for released history, and [`docs/CAPABILITY.md`](docs/CAPABILITY.md) for the
630
+ per-capability roadmap. Near-term items include **ITRF-precise frame reduction**
631
+ (polar motion and sub-arcsecond nutation on top of the shipped GMST-based
632
+ TEME&harr;ECEF), two-part Julian dates, tightly-coupled carrier-phase fusion, and
633
+ surfacing the loosely-/tightly-coupled GNSS/INS navigator across more packs. The
634
+ **quantum physics layer** is a **P2** item: the CAI accelerometer is now simulated from
635
+ first principles (Mach–Zehnder phase, projection noise, contrast decay, vibration
636
+ coupling), while the clock/time-transfer sensors are still driven by published
637
+ Allan/noise-budget coefficients. GMST-based TEME&harr;ECEF, the IERS
638
+ leap-second time systems (UTC/TAI/TT/UT1), SGP4/SDP4 orbit propagation (v0.7.0,
639
+ validated against the AIAA 2006-6753 vectors), and the runnable `gnss-ins` fusion
640
+ pack have all **shipped**, and the inertial velocity is exposed downstream. An active
641
+ stochastic time-spoof detector (Neyman–Pearson / χ²₁ energy test with Monte-Carlo
642
+ P_fa/P_md and a Security FoM of 1−P_md), a link-budget jamming model (J/S → effective
643
+ C/N₀ → loss of lock), multi-constellation availability, a single-axis (1-DOF)
546
644
  IMU error budget, two independent (clock + position) Kalman estimators reported as a
547
- combined FoM, real constellation geometry from TLEs, an HTML scorecard report, a
548
- clock-stability-based spoof-detectability bound, geometry-derived GNSS availability
645
+ combined FoM, real constellation geometry from TLEs, an HTML scorecard report,
646
+ geometry-derived GNSS availability
549
647
  *and* dilution of precision from Keplerian orbits with eccentricity and J2 drift,
550
648
  Monte Carlo confidence bands, trade-study parameter sweeps, an in-browser WebAssembly
551
649
  playground, and optional Python (PyO3) and WebAssembly (wasm-bindgen) bindings have
@@ -563,10 +661,12 @@ entry for every user-visible change. Participation is governed by our
563
661
 
564
662
  If you use Kshana in academic or technical work, please cite it. Machine-readable
565
663
  metadata is in [`CITATION.cff`](CITATION.cff) (GitHub renders a "Cite this repository"
566
- button from it); cite the version you used (e.g. `v0.9.2`) together with the
567
- scenario and seed for full reproducibility. An archival DOI (Zenodo) is planned.
664
+ button from it); cite the version you used (e.g. `v0.11.0`) together with the
665
+ scenario and seed for full reproducibility. Every release is archived on Zenodo with
666
+ a citable DOI — the concept DOI [10.5281/zenodo.20528627](https://doi.org/10.5281/zenodo.20528627)
667
+ always resolves to the latest version.
568
668
 
569
- > Baweja, C. (2026). *Kshana — hybrid quantum/classical PNT performance simulator*. Ashforde OÜ. https://github.com/AshfordeOU/kshana
669
+ > Baweja, C. (2026). *Kshana — a PNT-resilience simulator with quantum-sensor performance models*. Ashforde OÜ. https://doi.org/10.5281/zenodo.20528627
570
670
 
571
671
  ## Versioning & releases
572
672
 
package/kshana.d.ts CHANGED
@@ -6,6 +6,30 @@
6
6
  */
7
7
  export function chart_svg(toml: string): string;
8
8
 
9
+ /**
10
+ * Decode a permalink token back into the scenario TOML; returns an empty string if the
11
+ * token is not valid Base64 or not valid UTF-8.
12
+ */
13
+ export function decode_permalink(token: string): string;
14
+
15
+ /**
16
+ * Encode a scenario TOML into a URL-safe permalink token for a `?s=` query parameter.
17
+ */
18
+ export function encode_permalink(toml: string): string;
19
+
20
+ /**
21
+ * Run a scenario; on failure return the structured error *kind* tag
22
+ * (`invalid_input`, `unsupported`, …) so the caller can branch on the failure
23
+ * category rather than parse the message. Returns an empty string on success.
24
+ */
25
+ export function error_kind(toml: string): string;
26
+
27
+ /**
28
+ * List the available scenario kinds and their metadata as a JSON array (name,
29
+ * description, required and optional fields), for programmatic introspection.
30
+ */
31
+ export function list_kinds(): string;
32
+
9
33
  /**
10
34
  * Run a scenario given as a TOML string; returns the result document as a JSON
11
35
  * string. Throws a JS error if the scenario is invalid.
@@ -27,6 +51,10 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
27
51
  export interface InitOutput {
28
52
  readonly memory: WebAssembly.Memory;
29
53
  readonly chart_svg: (a: number, b: number) => [number, number, number, number];
54
+ readonly decode_permalink: (a: number, b: number) => [number, number];
55
+ readonly encode_permalink: (a: number, b: number) => [number, number];
56
+ readonly error_kind: (a: number, b: number) => [number, number];
57
+ readonly list_kinds: () => [number, number];
30
58
  readonly run: (a: number, b: number) => [number, number, number, number];
31
59
  readonly summary: (a: number, b: number) => [number, number, number, number];
32
60
  readonly version: () => [number, number];
package/kshana.js CHANGED
@@ -26,6 +26,87 @@ export function chart_svg(toml) {
26
26
  }
27
27
  }
28
28
 
29
+ /**
30
+ * Decode a permalink token back into the scenario TOML; returns an empty string if the
31
+ * token is not valid Base64 or not valid UTF-8.
32
+ * @param {string} token
33
+ * @returns {string}
34
+ */
35
+ export function decode_permalink(token) {
36
+ let deferred2_0;
37
+ let deferred2_1;
38
+ try {
39
+ const ptr0 = passStringToWasm0(token, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
40
+ const len0 = WASM_VECTOR_LEN;
41
+ const ret = wasm.decode_permalink(ptr0, len0);
42
+ deferred2_0 = ret[0];
43
+ deferred2_1 = ret[1];
44
+ return getStringFromWasm0(ret[0], ret[1]);
45
+ } finally {
46
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Encode a scenario TOML into a URL-safe permalink token for a `?s=` query parameter.
52
+ * @param {string} toml
53
+ * @returns {string}
54
+ */
55
+ export function encode_permalink(toml) {
56
+ let deferred2_0;
57
+ let deferred2_1;
58
+ try {
59
+ const ptr0 = passStringToWasm0(toml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
60
+ const len0 = WASM_VECTOR_LEN;
61
+ const ret = wasm.encode_permalink(ptr0, len0);
62
+ deferred2_0 = ret[0];
63
+ deferred2_1 = ret[1];
64
+ return getStringFromWasm0(ret[0], ret[1]);
65
+ } finally {
66
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Run a scenario; on failure return the structured error *kind* tag
72
+ * (`invalid_input`, `unsupported`, …) so the caller can branch on the failure
73
+ * category rather than parse the message. Returns an empty string on success.
74
+ * @param {string} toml
75
+ * @returns {string}
76
+ */
77
+ export function error_kind(toml) {
78
+ let deferred2_0;
79
+ let deferred2_1;
80
+ try {
81
+ const ptr0 = passStringToWasm0(toml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
82
+ const len0 = WASM_VECTOR_LEN;
83
+ const ret = wasm.error_kind(ptr0, len0);
84
+ deferred2_0 = ret[0];
85
+ deferred2_1 = ret[1];
86
+ return getStringFromWasm0(ret[0], ret[1]);
87
+ } finally {
88
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * List the available scenario kinds and their metadata as a JSON array (name,
94
+ * description, required and optional fields), for programmatic introspection.
95
+ * @returns {string}
96
+ */
97
+ export function list_kinds() {
98
+ let deferred1_0;
99
+ let deferred1_1;
100
+ try {
101
+ const ret = wasm.list_kinds();
102
+ deferred1_0 = ret[0];
103
+ deferred1_1 = ret[1];
104
+ return getStringFromWasm0(ret[0], ret[1]);
105
+ } finally {
106
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
107
+ }
108
+ }
109
+
29
110
  /**
30
111
  * Run a scenario given as a TOML string; returns the result document as a JSON
31
112
  * string. Throws a JS error if the scenario is invalid.
package/kshana_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -4,8 +4,8 @@
4
4
  "collaborators": [
5
5
  "Chakshu Baweja <contact@ashforde.org>"
6
6
  ],
7
- "description": "Open hybrid quantum/classical PNT performance simulator",
8
- "version": "0.9.2",
7
+ "description": "Open, reproducible PNT-resilience simulator with quantum-sensor performance models",
8
+ "version": "0.11.0",
9
9
  "license": "Apache-2.0",
10
10
  "repository": {
11
11
  "type": "git",