gea-program 0.82.0__tar.gz → 0.83.1__tar.gz

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.
Files changed (428) hide show
  1. {gea_program-0.82.0/gea_program.egg-info → gea_program-0.83.1}/PKG-INFO +10 -6
  2. {gea_program-0.82.0 → gea_program-0.83.1}/README.md +9 -5
  3. {gea_program-0.82.0 → gea_program-0.83.1}/gea/__init__.py +1 -1
  4. {gea_program-0.82.0 → gea_program-0.83.1}/gea/acceptance_tests.py +154 -3
  5. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/IT_SECURITY.md +15 -1
  6. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/driller.md +1 -1
  7. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/install.md +2 -2
  8. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/reader.md +1 -1
  9. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/recorder.md +1 -1
  10. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/01-install.md +2 -2
  11. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/19-dossier-reader.md +1 -1
  12. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/22-updates.md +1 -1
  13. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/23-vpn.md +1 -1
  14. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/25-install-recorder.md +2 -2
  15. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/29-driller-rig.md +1 -1
  16. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial.md +2 -2
  17. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/vpn.md +2 -0
  18. {gea_program-0.82.0 → gea_program-0.83.1}/gea/icon.py +28 -1
  19. {gea_program-0.82.0 → gea_program-0.83.1}/gea/updates.py +4 -4
  20. {gea_program-0.82.0 → gea_program-0.83.1}/gea/vpn.py +8 -2
  21. {gea_program-0.82.0 → gea_program-0.83.1}/gea/web/app.html +1 -1
  22. {gea_program-0.82.0 → gea_program-0.83.1/gea_program.egg-info}/PKG-INFO +10 -6
  23. {gea_program-0.82.0 → gea_program-0.83.1}/pyproject.toml +1 -1
  24. {gea_program-0.82.0 → gea_program-0.83.1}/LICENSE +0 -0
  25. {gea_program-0.82.0 → gea_program-0.83.1}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  26. {gea_program-0.82.0 → gea_program-0.83.1}/gea/__main__.py +0 -0
  27. {gea_program-0.82.0 → gea_program-0.83.1}/gea/accuracy_statement.py +0 -0
  28. {gea_program-0.82.0 → gea_program-0.83.1}/gea/alarm_engine.py +0 -0
  29. {gea_program-0.82.0 → gea_program-0.83.1}/gea/alerts.py +0 -0
  30. {gea_program-0.82.0 → gea_program-0.83.1}/gea/backup.py +0 -0
  31. {gea_program-0.82.0 → gea_program-0.83.1}/gea/bench.py +0 -0
  32. {gea_program-0.82.0 → gea_program-0.83.1}/gea/bit_seismic.py +0 -0
  33. {gea_program-0.82.0 → gea_program-0.83.1}/gea/blind_harness.py +0 -0
  34. {gea_program-0.82.0 → gea_program-0.83.1}/gea/casing_design.py +0 -0
  35. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  36. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  37. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  38. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  39. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  40. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/barbados_110_consolidation.txt +0 -0
  41. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  42. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  43. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  44. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  45. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  46. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  47. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  48. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  49. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  50. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  51. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  52. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  53. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  54. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  55. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  56. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  57. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  58. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  59. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  60. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  61. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  62. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  63. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  64. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  65. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  66. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  67. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  68. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  69. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  70. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  71. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  72. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  73. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  74. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  75. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  76. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  77. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  78. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  79. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  80. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  81. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  82. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  83. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  84. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  85. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  86. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  87. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  88. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  89. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  90. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  91. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  92. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  93. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  94. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  95. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/l06_06_nl_survey.csv +0 -0
  96. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  97. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  98. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  99. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  100. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  101. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  102. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/med_160_sapropels.txt +0 -0
  103. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  104. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  105. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  106. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  107. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  108. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  109. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  110. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  111. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  112. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  113. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  114. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  115. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  116. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  117. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  118. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  119. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  120. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  121. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  122. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  123. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  124. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  125. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  126. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  127. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  128. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  129. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  130. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  131. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  132. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  133. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  134. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  135. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  136. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  137. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  138. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  139. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog_map.py +0 -0
  140. {gea_program-0.82.0 → gea_program-0.83.1}/gea/catalog_register.py +0 -0
  141. {gea_program-0.82.0 → gea_program-0.83.1}/gea/certificates.py +0 -0
  142. {gea_program-0.82.0 → gea_program-0.83.1}/gea/cli.py +0 -0
  143. {gea_program-0.82.0 → gea_program-0.83.1}/gea/client_reports.py +0 -0
  144. {gea_program-0.82.0 → gea_program-0.83.1}/gea/collision.py +0 -0
  145. {gea_program-0.82.0 → gea_program-0.83.1}/gea/config_versioning.py +0 -0
  146. {gea_program-0.82.0 → gea_program-0.83.1}/gea/conformance.py +0 -0
  147. {gea_program-0.82.0 → gea_program-0.83.1}/gea/control_room.py +0 -0
  148. {gea_program-0.82.0 → gea_program-0.83.1}/gea/correlation.py +0 -0
  149. {gea_program-0.82.0 → gea_program-0.83.1}/gea/dashboard.py +0 -0
  150. {gea_program-0.82.0 → gea_program-0.83.1}/gea/declarations.py +0 -0
  151. {gea_program-0.82.0 → gea_program-0.83.1}/gea/decline.py +0 -0
  152. {gea_program-0.82.0 → gea_program-0.83.1}/gea/deviation.py +0 -0
  153. {gea_program-0.82.0 → gea_program-0.83.1}/gea/dlis.py +0 -0
  154. {gea_program-0.82.0 → gea_program-0.83.1}/gea/dnp3.py +0 -0
  155. {gea_program-0.82.0 → gea_program-0.83.1}/gea/doctor.py +0 -0
  156. {gea_program-0.82.0 → gea_program-0.83.1}/gea/dossier.py +0 -0
  157. {gea_program-0.82.0 → gea_program-0.83.1}/gea/dossier_verify.py +0 -0
  158. {gea_program-0.82.0 → gea_program-0.83.1}/gea/downhole_engine.py +0 -0
  159. {gea_program-0.82.0 → gea_program-0.83.1}/gea/drift_monitor.py +0 -0
  160. {gea_program-0.82.0 → gea_program-0.83.1}/gea/drill_string.py +0 -0
  161. {gea_program-0.82.0 → gea_program-0.83.1}/gea/driller_link.py +0 -0
  162. {gea_program-0.82.0 → gea_program-0.83.1}/gea/earth_model.py +0 -0
  163. {gea_program-0.82.0 → gea_program-0.83.1}/gea/economics.py +0 -0
  164. {gea_program-0.82.0 → gea_program-0.83.1}/gea/ed25519.py +0 -0
  165. {gea_program-0.82.0 → gea_program-0.83.1}/gea/edr.py +0 -0
  166. {gea_program-0.82.0 → gea_program-0.83.1}/gea/elevation.py +0 -0
  167. {gea_program-0.82.0 → gea_program-0.83.1}/gea/etp.py +0 -0
  168. {gea_program-0.82.0 → gea_program-0.83.1}/gea/etp12_schemas.json +0 -0
  169. {gea_program-0.82.0 → gea_program-0.83.1}/gea/example_register_map.json +0 -0
  170. {gea_program-0.82.0 → gea_program-0.83.1}/gea/fat_sat.py +0 -0
  171. {gea_program-0.82.0 → gea_program-0.83.1}/gea/field_pull.py +0 -0
  172. {gea_program-0.82.0 → gea_program-0.83.1}/gea/files.py +0 -0
  173. {gea_program-0.82.0 → gea_program-0.83.1}/gea/fixtures/README.md +0 -0
  174. {gea_program-0.82.0 → gea_program-0.83.1}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
  175. {gea_program-0.82.0 → gea_program-0.83.1}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
  176. {gea_program-0.82.0 → gea_program-0.83.1}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
  177. {gea_program-0.82.0 → gea_program-0.83.1}/gea/fixtures/ne_110m_coastline.json +0 -0
  178. {gea_program-0.82.0 → gea_program-0.83.1}/gea/follower.py +0 -0
  179. {gea_program-0.82.0 → gea_program-0.83.1}/gea/forward_model.py +0 -0
  180. {gea_program-0.82.0 → gea_program-0.83.1}/gea/frac_hits.py +0 -0
  181. {gea_program-0.82.0 → gea_program-0.83.1}/gea/friction_priors.py +0 -0
  182. {gea_program-0.82.0 → gea_program-0.83.1}/gea/gamma.py +0 -0
  183. {gea_program-0.82.0 → gea_program-0.83.1}/gea/gauge_aging.py +0 -0
  184. {gea_program-0.82.0 → gea_program-0.83.1}/gea/gauge_specs.py +0 -0
  185. {gea_program-0.82.0 → gea_program-0.83.1}/gea/geodesy.py +0 -0
  186. {gea_program-0.82.0 → gea_program-0.83.1}/gea/geomag.py +0 -0
  187. {gea_program-0.82.0 → gea_program-0.83.1}/gea/gravity_reference.py +0 -0
  188. {gea_program-0.82.0 → gea_program-0.83.1}/gea/hartip.py +0 -0
  189. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/TESTER_GUIDE.md +0 -0
  190. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/alarms.md +0 -0
  191. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/alerts.md +0 -0
  192. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/audit-update.md +0 -0
  193. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/backup.md +0 -0
  194. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/bit-image.md +0 -0
  195. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/casing.md +0 -0
  196. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/catalog.md +0 -0
  197. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/charts.md +0 -0
  198. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/collision.md +0 -0
  199. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/company-sign-in.md +0 -0
  200. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/conformance.md +0 -0
  201. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/control-room.md +0 -0
  202. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/data-in.md +0 -0
  203. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/declare.md +0 -0
  204. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/decline.md +0 -0
  205. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/dlis.md +0 -0
  206. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/doctor.md +0 -0
  207. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/dossier.md +0 -0
  208. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/drift.md +0 -0
  209. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/drillstring.md +0 -0
  210. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/economics.md +0 -0
  211. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/edr.md +0 -0
  212. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/etp.md +0 -0
  213. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/field-ports.md +0 -0
  214. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/files.md +0 -0
  215. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/frac-hits.md +0 -0
  216. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/historian.md +0 -0
  217. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/https.md +0 -0
  218. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/hydraulics.md +0 -0
  219. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/instruments.md +0 -0
  220. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/interval.md +0 -0
  221. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/invoice-check.md +0 -0
  222. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/map.md +0 -0
  223. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/month-end.md +0 -0
  224. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/notifications.md +0 -0
  225. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/opseis.md +0 -0
  226. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/osdu.md +0 -0
  227. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/pad-summary.md +0 -0
  228. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/patches.md +0 -0
  229. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/penetrator.md +0 -0
  230. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/plan.md +0 -0
  231. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/pore-pressure.md +0 -0
  232. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/ppdm.md +0 -0
  233. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/quakeml.md +0 -0
  234. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/quality.md +0 -0
  235. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/records.md +0 -0
  236. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/report-history.md +0 -0
  237. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/rig-time.md +0 -0
  238. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/rocks.md +0 -0
  239. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/seedlink.md +0 -0
  240. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/seismic.md +0 -0
  241. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/setup.md +0 -0
  242. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/simulation.md +0 -0
  243. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/site.md +0 -0
  244. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/sites.md +0 -0
  245. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/slip.md +0 -0
  246. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/soak.md +0 -0
  247. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/sra.md +0 -0
  248. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/start.md +0 -0
  249. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/structure.md +0 -0
  250. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tools.md +0 -0
  251. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/torque-drag.md +0 -0
  252. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/transients.md +0 -0
  253. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/02-sign-in.md +0 -0
  254. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/03-site.md +0 -0
  255. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/04-add-well.md +0 -0
  256. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/05-records.md +0 -0
  257. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/06-well-page.md +0 -0
  258. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/07-declare.md +0 -0
  259. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/08-patches.md +0 -0
  260. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/09-alarms.md +0 -0
  261. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/10-control-room.md +0 -0
  262. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/11-summary-month.md +0 -0
  263. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/12-where-the-well-is.md +0 -0
  264. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/13-drilling-pages.md +0 -0
  265. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/14-production-pages.md +0 -0
  266. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/15-seismic.md +0 -0
  267. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/16-seismicity.md +0 -0
  268. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/17-recorder-office.md +0 -0
  269. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/18-reports.md +0 -0
  270. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/20-admin.md +0 -0
  271. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/21-upkeep.md +0 -0
  272. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/24-the-box.md +0 -0
  273. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/26-monitor.md +0 -0
  274. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/27-mirror-vpn.md +0 -0
  275. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/tutorial/28-driller-office.md +0 -0
  276. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/upkeep.md +0 -0
  277. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/vibration.md +0 -0
  278. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/well-report.md +0 -0
  279. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/well-tests.md +0 -0
  280. {gea_program-0.82.0 → gea_program-0.83.1}/gea/help/well3d.md +0 -0
  281. {gea_program-0.82.0 → gea_program-0.83.1}/gea/helplib.py +0 -0
  282. {gea_program-0.82.0 → gea_program-0.83.1}/gea/housekeeping.py +0 -0
  283. {gea_program-0.82.0 → gea_program-0.83.1}/gea/hydraulics.py +0 -0
  284. {gea_program-0.82.0 → gea_program-0.83.1}/gea/interval.py +0 -0
  285. {gea_program-0.82.0 → gea_program-0.83.1}/gea/inverse_engine.py +0 -0
  286. {gea_program-0.82.0 → gea_program-0.83.1}/gea/invoice_check.py +0 -0
  287. {gea_program-0.82.0 → gea_program-0.83.1}/gea/jobs.py +0 -0
  288. {gea_program-0.82.0 → gea_program-0.83.1}/gea/launcher.py +0 -0
  289. {gea_program-0.82.0 → gea_program-0.83.1}/gea/live_ports.py +0 -0
  290. {gea_program-0.82.0 → gea_program-0.83.1}/gea/loadtest.py +0 -0
  291. {gea_program-0.82.0 → gea_program-0.83.1}/gea/matplotlib_demo.py +0 -0
  292. {gea_program-0.82.0 → gea_program-0.83.1}/gea/modbus.py +0 -0
  293. {gea_program-0.82.0 → gea_program-0.83.1}/gea/modbus_rtu.py +0 -0
  294. {gea_program-0.82.0 → gea_program-0.83.1}/gea/model_card.py +0 -0
  295. {gea_program-0.82.0 → gea_program-0.83.1}/gea/month_end.py +0 -0
  296. {gea_program-0.82.0 → gea_program-0.83.1}/gea/mqtt_port.py +0 -0
  297. {gea_program-0.82.0 → gea_program-0.83.1}/gea/notify.py +0 -0
  298. {gea_program-0.82.0 → gea_program-0.83.1}/gea/oidc.py +0 -0
  299. {gea_program-0.82.0 → gea_program-0.83.1}/gea/oidc_mock.py +0 -0
  300. {gea_program-0.82.0 → gea_program-0.83.1}/gea/op_seismicity.py +0 -0
  301. {gea_program-0.82.0 → gea_program-0.83.1}/gea/opcua_port.py +0 -0
  302. {gea_program-0.82.0 → gea_program-0.83.1}/gea/operator_app.py +0 -0
  303. {gea_program-0.82.0 → gea_program-0.83.1}/gea/osdu.py +0 -0
  304. {gea_program-0.82.0 → gea_program-0.83.1}/gea/pad_summary.py +0 -0
  305. {gea_program-0.82.0 → gea_program-0.83.1}/gea/patches.py +0 -0
  306. {gea_program-0.82.0 → gea_program-0.83.1}/gea/pdf_report.py +0 -0
  307. {gea_program-0.82.0 → gea_program-0.83.1}/gea/penetrator.py +0 -0
  308. {gea_program-0.82.0 → gea_program-0.83.1}/gea/permits.py +0 -0
  309. {gea_program-0.82.0 → gea_program-0.83.1}/gea/piwebapi.py +0 -0
  310. {gea_program-0.82.0 → gea_program-0.83.1}/gea/pore_pressure.py +0 -0
  311. {gea_program-0.82.0 → gea_program-0.83.1}/gea/ports.py +0 -0
  312. {gea_program-0.82.0 → gea_program-0.83.1}/gea/ppdm.py +0 -0
  313. {gea_program-0.82.0 → gea_program-0.83.1}/gea/profile_catalog.py +0 -0
  314. {gea_program-0.82.0 → gea_program-0.83.1}/gea/project.py +0 -0
  315. {gea_program-0.82.0 → gea_program-0.83.1}/gea/qt6_downhole_app.py +0 -0
  316. {gea_program-0.82.0 → gea_program-0.83.1}/gea/quakeml.py +0 -0
  317. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reader.py +0 -0
  318. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reader_app.py +0 -0
  319. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reconciler.py +0 -0
  320. {gea_program-0.82.0 → gea_program-0.83.1}/gea/recorder_link.py +0 -0
  321. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  322. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  323. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/WMM2025.COF +0 -0
  324. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
  325. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/eia_prices.provenance.json +0 -0
  326. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/eia_wti_daily.csv.gz +0 -0
  327. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/iscwsa_rev4_example.json +0 -0
  328. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/iscwsa_rev5_example.json +0 -0
  329. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/l0701_sonic_gr.las.gz +0 -0
  330. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
  331. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/libmseed_steim.provenance.json +0 -0
  332. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  333. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  334. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/libmseed_steim2_512.mseed +0 -0
  335. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/mahoning_example.json +0 -0
  336. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/mud_motor_specs.json +0 -0
  337. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/owsg_tool_models.json +0 -0
  338. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/penetrator_ratings.json +0 -0
  339. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/seismicity_protocols.json +0 -0
  340. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/tool_sources.json +0 -0
  341. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/us_outline.json +0 -0
  342. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/us_outline.provenance.json +0 -0
  343. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_3d.provenance.json +0 -0
  344. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_f4_interpretation.las.gz +0 -0
  345. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_f4_logs.provenance.json +0 -0
  346. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_f4_lwd.las.gz +0 -0
  347. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_surfaces.json.gz +0 -0
  348. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_traj_F-10.xml.gz +0 -0
  349. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_traj_F-4.xml.gz +0 -0
  350. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
  351. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
  352. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
  353. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
  354. {gea_program-0.82.0 → gea_program-0.83.1}/gea/reference/volve_well_picks.csv.gz +0 -0
  355. {gea_program-0.82.0 → gea_program-0.83.1}/gea/report_history.py +0 -0
  356. {gea_program-0.82.0 → gea_program-0.83.1}/gea/rig_state.py +0 -0
  357. {gea_program-0.82.0 → gea_program-0.83.1}/gea/rock_inventory.py +0 -0
  358. {gea_program-0.82.0 → gea_program-0.83.1}/gea/sample_record.py +0 -0
  359. {gea_program-0.82.0 → gea_program-0.83.1}/gea/sample_well_profile.csv +0 -0
  360. {gea_program-0.82.0 → gea_program-0.83.1}/gea/sbom.py +0 -0
  361. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seedlink.py +0 -0
  362. {gea_program-0.82.0 → gea_program-0.83.1}/gea/segy.py +0 -0
  363. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic.py +0 -0
  364. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_array.py +0 -0
  365. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_assoc.py +0 -0
  366. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_detect.py +0 -0
  367. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_film.py +0 -0
  368. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_harmonic.py +0 -0
  369. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_qc.py +0 -0
  370. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_response.py +0 -0
  371. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_signature.py +0 -0
  372. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_track.py +0 -0
  373. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_uncertainty.py +0 -0
  374. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_unlisted.py +0 -0
  375. {gea_program-0.82.0 → gea_program-0.83.1}/gea/seismic_watch.py +0 -0
  376. {gea_program-0.82.0 → gea_program-0.83.1}/gea/sensor_swap.py +0 -0
  377. {gea_program-0.82.0 → gea_program-0.83.1}/gea/series_cache.py +0 -0
  378. {gea_program-0.82.0 → gea_program-0.83.1}/gea/service.py +0 -0
  379. {gea_program-0.82.0 → gea_program-0.83.1}/gea/service_life.py +0 -0
  380. {gea_program-0.82.0 → gea_program-0.83.1}/gea/setup_checklist.py +0 -0
  381. {gea_program-0.82.0 → gea_program-0.83.1}/gea/shapefile.py +0 -0
  382. {gea_program-0.82.0 → gea_program-0.83.1}/gea/shell.py +0 -0
  383. {gea_program-0.82.0 → gea_program-0.83.1}/gea/shut_in.py +0 -0
  384. {gea_program-0.82.0 → gea_program-0.83.1}/gea/simulation.py +0 -0
  385. {gea_program-0.82.0 → gea_program-0.83.1}/gea/site_map.py +0 -0
  386. {gea_program-0.82.0 → gea_program-0.83.1}/gea/sla_report.py +0 -0
  387. {gea_program-0.82.0 → gea_program-0.83.1}/gea/slip.py +0 -0
  388. {gea_program-0.82.0 → gea_program-0.83.1}/gea/soak.py +0 -0
  389. {gea_program-0.82.0 → gea_program-0.83.1}/gea/sra.py +0 -0
  390. {gea_program-0.82.0 → gea_program-0.83.1}/gea/store_forward.py +0 -0
  391. {gea_program-0.82.0 → gea_program-0.83.1}/gea/strata_join.py +0 -0
  392. {gea_program-0.82.0 → gea_program-0.83.1}/gea/structure.py +0 -0
  393. {gea_program-0.82.0 → gea_program-0.83.1}/gea/supervisor.py +0 -0
  394. {gea_program-0.82.0 → gea_program-0.83.1}/gea/survey_cmd.py +0 -0
  395. {gea_program-0.82.0 → gea_program-0.83.1}/gea/survey_view.py +0 -0
  396. {gea_program-0.82.0 → gea_program-0.83.1}/gea/telemetry.py +0 -0
  397. {gea_program-0.82.0 → gea_program-0.83.1}/gea/timestamp.py +0 -0
  398. {gea_program-0.82.0 → gea_program-0.83.1}/gea/tls.py +0 -0
  399. {gea_program-0.82.0 → gea_program-0.83.1}/gea/tool_catalog.py +0 -0
  400. {gea_program-0.82.0 → gea_program-0.83.1}/gea/tool_library.py +0 -0
  401. {gea_program-0.82.0 → gea_program-0.83.1}/gea/tool_taxonomy.py +0 -0
  402. {gea_program-0.82.0 → gea_program-0.83.1}/gea/torque_drag.py +0 -0
  403. {gea_program-0.82.0 → gea_program-0.83.1}/gea/transient.py +0 -0
  404. {gea_program-0.82.0 → gea_program-0.83.1}/gea/tray.py +0 -0
  405. {gea_program-0.82.0 → gea_program-0.83.1}/gea/tutorial.py +0 -0
  406. {gea_program-0.82.0 → gea_program-0.83.1}/gea/vibration.py +0 -0
  407. {gea_program-0.82.0 → gea_program-0.83.1}/gea/web/reader.html +0 -0
  408. {gea_program-0.82.0 → gea_program-0.83.1}/gea/well3d.py +0 -0
  409. {gea_program-0.82.0 → gea_program-0.83.1}/gea/well_assembler.py +0 -0
  410. {gea_program-0.82.0 → gea_program-0.83.1}/gea/well_records.py +0 -0
  411. {gea_program-0.82.0 → gea_program-0.83.1}/gea/well_report.py +0 -0
  412. {gea_program-0.82.0 → gea_program-0.83.1}/gea/well_test_validation.py +0 -0
  413. {gea_program-0.82.0 → gea_program-0.83.1}/gea/wellplan.py +0 -0
  414. {gea_program-0.82.0 → gea_program-0.83.1}/gea/wellpos.py +0 -0
  415. {gea_program-0.82.0 → gea_program-0.83.1}/gea/winident.py +0 -0
  416. {gea_program-0.82.0 → gea_program-0.83.1}/gea/wits0.py +0 -0
  417. {gea_program-0.82.0 → gea_program-0.83.1}/gea/witsml.py +0 -0
  418. {gea_program-0.82.0 → gea_program-0.83.1}/gea/workspace.py +0 -0
  419. {gea_program-0.82.0 → gea_program-0.83.1}/gea/workspaces.py +0 -0
  420. {gea_program-0.82.0 → gea_program-0.83.1}/gea/x25519.py +0 -0
  421. {gea_program-0.82.0 → gea_program-0.83.1}/gea/xlsx_read.py +0 -0
  422. {gea_program-0.82.0 → gea_program-0.83.1}/gea_program.egg-info/SOURCES.txt +0 -0
  423. {gea_program-0.82.0 → gea_program-0.83.1}/gea_program.egg-info/dependency_links.txt +0 -0
  424. {gea_program-0.82.0 → gea_program-0.83.1}/gea_program.egg-info/entry_points.txt +0 -0
  425. {gea_program-0.82.0 → gea_program-0.83.1}/gea_program.egg-info/requires.txt +0 -0
  426. {gea_program-0.82.0 → gea_program-0.83.1}/gea_program.egg-info/top_level.txt +0 -0
  427. {gea_program-0.82.0 → gea_program-0.83.1}/setup.cfg +0 -0
  428. {gea_program-0.82.0 → gea_program-0.83.1}/tests/test_acceptance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gea-program
3
- Version: 0.82.0
3
+ Version: 0.83.1
4
4
  Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
5
5
  Author: Daniel T. Murphy
6
6
  License: MPL-2.0
@@ -542,8 +542,12 @@ every configuration: enter the hub's address, **Make the network**, copy
542
542
  `gea-vpn-hub.zip` to the hub and run `sudo sh install-hub.sh`; install
543
543
  WireGuard on the office PC from wireguard.com and import the office's
544
544
  `gea-vpn.conf`; add a member per computer and hand it its zip (a box's
545
- holds `vpn.sh`, run once on the Pi; a window imports its `gea-vpn.conf`),
546
- then run the hub installer again. The keys stay in
545
+ holds `vpn.sh`, run once on the Pi; every other member installs the
546
+ client program **GEA-VPN** once - `vpn/`, `GEA-VPN-Setup-<version>.exe`
547
+ and `GEA-VPN-<version>.tar.gz` on every release, since 0.83.0 - and drops
548
+ its zip on the program's page at `http://127.0.0.1:8795/`: the tunnel is
549
+ up from then on, at every start, and the page says when the hub and the
550
+ office answer), then run the hub installer again. The keys stay in
547
551
  `keys\vpn\network.json`, owner-only, in the backup and never in the
548
552
  dossier. From a terminal: `gea vpn --workspace C:\site --create
549
553
  vpn.pad3site.com`, `gea vpn --workspace C:\site --add "Pad 3 box" --kind
@@ -843,7 +847,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
843
847
  reader made from the workspace knows the site's key fingerprints, so it
844
848
  says whether a dossier is the site's; it allows no network request, and it
845
849
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
846
- it installed, every release also carries `GEA-Reader-Setup-0.82.0.exe`: GEA
850
+ it installed, every release also carries `GEA-Reader-Setup-0.83.1.exe`: GEA
847
851
  Reader as a Windows program of its own - its own icon and taskbar button,
848
852
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
849
853
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -1608,7 +1612,7 @@ attaches the zips to the GitHub release of that tag.
1608
1612
 
1609
1613
  ### The Windows installer
1610
1614
 
1611
- Every release also carries `GEA-Program-Setup-0.82.0.exe` (for 0.82.0): the
1615
+ Every release also carries `GEA-Program-Setup-0.83.1.exe` (for 0.83.1): the
1612
1616
  same Windows kit installed like any Windows program, for the signed-in user
1613
1617
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1614
1618
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1627,7 +1631,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1627
1631
  software deployment:
1628
1632
 
1629
1633
  ```
1630
- GEA-Program-Setup-0.82.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1634
+ GEA-Program-Setup-0.83.1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1631
1635
  ```
1632
1636
 
1633
1637
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -503,8 +503,12 @@ every configuration: enter the hub's address, **Make the network**, copy
503
503
  `gea-vpn-hub.zip` to the hub and run `sudo sh install-hub.sh`; install
504
504
  WireGuard on the office PC from wireguard.com and import the office's
505
505
  `gea-vpn.conf`; add a member per computer and hand it its zip (a box's
506
- holds `vpn.sh`, run once on the Pi; a window imports its `gea-vpn.conf`),
507
- then run the hub installer again. The keys stay in
506
+ holds `vpn.sh`, run once on the Pi; every other member installs the
507
+ client program **GEA-VPN** once - `vpn/`, `GEA-VPN-Setup-<version>.exe`
508
+ and `GEA-VPN-<version>.tar.gz` on every release, since 0.83.0 - and drops
509
+ its zip on the program's page at `http://127.0.0.1:8795/`: the tunnel is
510
+ up from then on, at every start, and the page says when the hub and the
511
+ office answer), then run the hub installer again. The keys stay in
508
512
  `keys\vpn\network.json`, owner-only, in the backup and never in the
509
513
  dossier. From a terminal: `gea vpn --workspace C:\site --create
510
514
  vpn.pad3site.com`, `gea vpn --workspace C:\site --add "Pad 3 box" --kind
@@ -804,7 +808,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
804
808
  reader made from the workspace knows the site's key fingerprints, so it
805
809
  says whether a dossier is the site's; it allows no network request, and it
806
810
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
807
- it installed, every release also carries `GEA-Reader-Setup-0.82.0.exe`: GEA
811
+ it installed, every release also carries `GEA-Reader-Setup-0.83.1.exe`: GEA
808
812
  Reader as a Windows program of its own - its own icon and taskbar button,
809
813
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
810
814
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -1569,7 +1573,7 @@ attaches the zips to the GitHub release of that tag.
1569
1573
 
1570
1574
  ### The Windows installer
1571
1575
 
1572
- Every release also carries `GEA-Program-Setup-0.82.0.exe` (for 0.82.0): the
1576
+ Every release also carries `GEA-Program-Setup-0.83.1.exe` (for 0.83.1): the
1573
1577
  same Windows kit installed like any Windows program, for the signed-in user
1574
1578
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1575
1579
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1588,7 +1592,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1588
1592
  software deployment:
1589
1593
 
1590
1594
  ```
1591
- GEA-Program-Setup-0.82.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1595
+ GEA-Program-Setup-0.83.1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1592
1596
  ```
1593
1597
 
1594
1598
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.82.0"
126
+ __version__ = "0.83.1"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -15246,7 +15246,7 @@ def section_do_reader_program(tmp: str) -> None:
15246
15246
  marks = _re.findall(r'attach-kit\.sh "[^"]*" "[^"]+" "([^"]+)"', wf)
15247
15247
  v = __version__
15248
15248
  assets = [f"gea-program-{v}-win64.zip", f"GEA-Program-Setup-{v}.exe", f"gea-program-{v}-linux-x86_64.zip", f"GEA-Reader-Setup-{v}.exe", f"GEA-Reader-portable-{v}.zip",
15249
- f"GEA-Recorder-{v}.tar.gz", f"GEA-Driller-{v}.tar.gz"]
15249
+ f"GEA-Recorder-{v}.tar.gz", f"GEA-Driller-{v}.tar.gz", f"GEA-VPN-Setup-{v}.exe", f"GEA-VPN-{v}.tar.gz"]
15250
15250
  app_id = _re.search(r"AppId=\{\{([0-9A-F-]+)\}", iss)
15251
15251
  c3 = {
15252
15252
  "kit": {"GEA-Reader.html", "GEA-Reader.cmd", "README.txt", "MANIFEST.json", "SHA256SUMS.txt", "reader.ico", "app/gea_reader.py", "app/winident.py",
@@ -15266,7 +15266,7 @@ def section_do_reader_program(tmp: str) -> None:
15266
15266
  and '-m gea_reader ""%1""' in iss,
15267
15267
  "workflow": "windows-reader:" in wf and "tools/build_reader.py" in wf and "tools\\reader_installer.iss" in wf and "-m gea_reader --selftest" in wf
15268
15268
  and "the right-click entry is still there" in wf
15269
- and all(sum(mk in a_ for mk in marks) == 1 for a_ in assets) and len(marks) == 7,
15269
+ and all(sum(bool(_re.search(mk, a_)) for mk in marks) == 1 for a_ in assets) and len(marks) == 9,
15270
15270
  }
15271
15271
  failed3 = [k for k, v_ in c3.items() if not v_]
15272
15272
  ok(not failed3,
@@ -16219,7 +16219,8 @@ def section_dt_vpn(tmp: str) -> None:
16219
16219
  c3 = {
16220
16220
  "written": set(written) == {"hub", "office", box["id"], rd["id"]},
16221
16221
  "hub_zip": hub_names == ["README.txt", "gea-vpn.conf", "install-hub.sh"] and "wg syncconf" in install_sh and "PORT=51820" in install_sh and "$PORT/udp" in install_sh and "ip_forward" in install_sh and "IFACE=gea-vpn" in install_sh and "wg-quick@$IFACE" in install_sh,
16222
- "box_zip": box_names == ["gea-vpn.conf", "vpn.sh"] and box_conf_z == (root / box["id"] / "gea-vpn.conf").read_text(encoding="utf-8") and "IFACE=gea-vpn" in vpn_sh and "wg-quick@$IFACE" in vpn_sh and "wireguard" in vpn_sh,
16222
+ # the files are written anew below (after the removal) with a new "made" line: the comparison leaves the first line out
16223
+ "box_zip": box_names == ["gea-vpn.conf", "vpn.sh"] and box_conf_z.split("\n", 1)[1] == (root / box["id"] / "gea-vpn.conf").read_text(encoding="utf-8").split("\n", 1)[1] and "IFACE=gea-vpn" in vpn_sh and "wg-quick@$IFACE" in vpn_sh and "wireguard" in vpn_sh,
16223
16224
  "reader_zip": rd_names == ["README.txt", "gea-vpn.conf"],
16224
16225
  "sh_n": sh_ok in (None, True),
16225
16226
  "wg_quick_strip": strip_ok in (None, True),
@@ -17280,6 +17281,155 @@ def section_dz_textbook_oracle(tmp: str) -> None:
17280
17281
  "the self-test holds the policy to the oracle as well; the help names the bar and the ceiling" + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
17281
17282
 
17282
17283
 
17284
+ def section_ea_vpn_client(tmp: str) -> None:
17285
+ """Section EA - GEA-VPN, the client program: standalone (the standard library and nothing of GEA), the connect
17286
+ information read from the zip GEA itself writes for a member and from pasted text, refused when wrong, its
17287
+ public key the one GEA has for the member; the page waiting, taking the information, refusing a request without
17288
+ its own header, forgetting; the records owner-only with a log; `wg show` parsed; the self-test from the command
17289
+ line; the Linux kit built (the wheel, install.sh, the sums); the Windows setup script, the workflow's jobs and
17290
+ marks, the icon, the kit names in the updates, the member's README, the card, the help, IT_SECURITY."""
17291
+ import importlib
17292
+ import importlib.util as _ilu
17293
+ import io as _io
17294
+ import re as _re
17295
+ import subprocess as _sp
17296
+ import zipfile as _zf
17297
+ from . import __version__
17298
+ from . import helplib as H
17299
+ from . import icon as IC
17300
+ from . import updates as UP
17301
+ from . import vpn as VP
17302
+ from . import x25519 as X
17303
+ from .workspace import Workspace
17304
+ pkg = Path(__file__).parent
17305
+ src = pkg.parent / "vpn"
17306
+ d = Path(tmp, "ea"); d.mkdir()
17307
+ if not (src / "gea_vpn" / "__init__.py").is_file():
17308
+ ok(True, "EA GEA-VPN's program (vpn/) is not beside this installation; the kits carry it - nothing to check here")
17309
+ return
17310
+ if str(src) not in sys.path:
17311
+ sys.path.insert(0, str(src))
17312
+ GV = importlib.import_module("gea_vpn"); GB = importlib.import_module("gea_vpn.bundle"); GS = importlib.import_module("gea_vpn.service"); GW = importlib.import_module("gea_vpn.wg")
17313
+ # -- EA1 the program ---------------------------------------------------------------------------------------------------------
17314
+ imports = set()
17315
+ for p_ in (src / "gea_vpn").glob("*.py"):
17316
+ for m_ in _re.findall(r"^\s*(?:from|import)\s+([a-zA-Z_][\w.]*)", p_.read_text(encoding="utf-8"), flags=_re.M):
17317
+ imports.add(m_.split(".")[0])
17318
+ foreign = {m_ for m_ in imports if m_ not in sys.stdlib_module_names and m_ not in ("gea_vpn",)} if hasattr(sys, "stdlib_module_names") else set()
17319
+ ws = Workspace.create(str(d / "ws"), "Pad 3 vpn", actor="tester")
17320
+ VP.create(ws, "tester", "vpn.pad3site.com")
17321
+ m = VP.add_member(ws, "tester", "Pad 3 rig PC", "driller")
17322
+ written = VP.write_bundles(ws, "tester")
17323
+ zip_bytes = Path(written[m["id"]]["zip"]).read_bytes()
17324
+ info = GB.read_connect_info(zip_bytes, os.path.basename(written[m["id"]]["zip"]))
17325
+ net = VP.load(ws)
17326
+ office = next(x for x in net["members"] if x["kind"] == "office")
17327
+ readme = Path(written[m["id"]]["dir"], "README.txt").read_text(encoding="utf-8")
17328
+ text_info = GB.check_conf(Path(written[m["id"]]["conf"]).read_text(encoding="utf-8"))
17329
+ refused = []
17330
+ for bad in (b"hello", b"PK\x03\x04junk", Path(written[m["id"]]["conf"]).read_text(encoding="utf-8").replace(":51820", "").encode(),
17331
+ Path(written[m["id"]]["conf"]).read_text(encoding="utf-8").replace("[Peer]", "[Peer]\nPublicKey = AAAA\n[Peer]").encode()):
17332
+ try:
17333
+ GB.read_connect_info(bad, "x.conf"); refused.append(False)
17334
+ except GB.BundleError:
17335
+ refused.append(True)
17336
+ cl = GS.Client(data_dir=str(d / "data"), dry=True)
17337
+ srv = GS.Server(cl, port=0); srv.start()
17338
+ try:
17339
+ import urllib.error
17340
+ import urllib.request
17341
+ with urllib.request.urlopen(srv.url + "/live.json", timeout=5) as r_:
17342
+ l0 = json.load(r_)
17343
+ rq = urllib.request.Request(srv.url + "/api/connect", data=json.dumps({"text": info["conf"]}).encode(), headers={"Content-Type": "application/json"}, method="POST")
17344
+ try:
17345
+ urllib.request.urlopen(rq, timeout=5); no_header = False
17346
+ except urllib.error.HTTPError as e:
17347
+ no_header = e.code == 403
17348
+ rq = urllib.request.Request(srv.url + "/api/connect", data=json.dumps({"text": info["conf"], "by": "tester"}).encode(), headers={"Content-Type": "application/json", "X-GEA-VPN": "1", "Origin": "http://evil.example"}, method="POST")
17349
+ try:
17350
+ urllib.request.urlopen(rq, timeout=5); foreign_origin = False
17351
+ except urllib.error.HTTPError as e:
17352
+ foreign_origin = e.code == 403
17353
+ # the zip itself, as the page takes it from a drop
17354
+ bnd = "----gea"; body = (f"--{bnd}\r\nContent-Disposition: form-data; name=\"by\"\r\n\r\ntester\r\n--{bnd}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"gea-vpn-x.zip\"\r\nContent-Type: application/zip\r\n\r\n").encode() + zip_bytes + f"\r\n--{bnd}--\r\n".encode()
17355
+ rq = urllib.request.Request(srv.url + "/api/connect", data=body, headers={"Content-Type": f"multipart/form-data; boundary={bnd}", "X-GEA-VPN": "1"}, method="POST")
17356
+ with urllib.request.urlopen(rq, timeout=5) as r_:
17357
+ res = json.load(r_)
17358
+ with urllib.request.urlopen(srv.url + "/live.json", timeout=5) as r_:
17359
+ l1 = json.load(r_)
17360
+ with urllib.request.urlopen(srv.url + "/health", timeout=5) as r_:
17361
+ hl = json.load(r_)
17362
+ mode = os.stat(cl.state.conf).st_mode & 0o777
17363
+ rq = urllib.request.Request(srv.url + "/api/forget", data=b'{"by":"tester"}', headers={"Content-Type": "application/json", "X-GEA-VPN": "1"}, method="POST")
17364
+ with urllib.request.urlopen(rq, timeout=5) as r_:
17365
+ json.load(r_)
17366
+ with urllib.request.urlopen(srv.url + "/live.json", timeout=5) as r_:
17367
+ l2 = json.load(r_)
17368
+ finally:
17369
+ srv.stop()
17370
+ dump = "PRIV\tPUB\t0\toff\n" + "HUBKEY\tPSK\t203.0.113.10:51820\t10.77.0.1/32,10.77.0.2/32\t" + str(int(time.time()) - 40) + "\t1024\t2048\t25\n"
17371
+ pd = GW.parse_dump(dump)
17372
+ wst = GW.status()
17373
+ env = dict(os.environ); env["PYTHONPATH"] = str(src)
17374
+ r_st = _sp.run([sys.executable, "-m", "gea_vpn", "selftest", "--json"], capture_output=True, text=True, env=env, cwd=str(d))
17375
+ try:
17376
+ stj = json.loads(r_st.stdout)
17377
+ except ValueError:
17378
+ stj = {}
17379
+ c1 = {
17380
+ "standalone": not foreign and GV.__version__ == __version__ and "numpy" not in imports,
17381
+ "zip_read": info["name"] == "Pad 3 rig PC" and info["kind"] == "driller" and info["address"] == m["address"] and info["hub"]["host"] == "vpn.pad3site.com" and info["hub"]["port"] == 51820
17382
+ and info["hub"]["address"] == net["hub"]["address"] and info["office_address"] == office["address"] and info["public_key"] == m["public_key"] and info["preshared"] and info["keepalive_s"] == 25
17383
+ and text_info["public_key"] == m["public_key"],
17384
+ "refusals": all(refused) and len(refused) == 4,
17385
+ "page": l0["phase"] in ("waiting", "no-wireguard") and l0["member"] is None and no_header and foreign_origin and res["ok"] and res["member"]["address"] == m["address"]
17386
+ and l1["member"]["name"] == "Pad 3 rig PC" and l1["source"] == "gea-vpn-x.zip" and hl["member"] == m["address"] and (os.name == "nt" or mode == 0o600)
17387
+ and l2["member"] is None and not os.path.isfile(cl.state.conf) and any("forget" in x for x in l2["log"]) and any("connect: Pad 3 rig PC" in x for x in l2["log"]),
17388
+ "dump": pd["public_key"] == "PUB" and len(pd["peers"]) == 1 and pd["peers"][0]["endpoint"] == "203.0.113.10:51820" and pd["peers"][0]["rx_bytes"] == 1024 and pd["peers"][0]["keepalive_s"] == 25
17389
+ and isinstance(wst.get("installed"), bool),
17390
+ "selftest": r_st.returncode == 0 and stj.get("ok") and len(stj.get("checks", [])) >= 6,
17391
+ }
17392
+ failed1 = [k for k, v in c1.items() if not v]
17393
+ ok(not failed1,
17394
+ "EA1 GEA-VPN is the standard library and nothing of GEA; it reads the zip GEA writes for a member - the name, the kind, the address, the hub, the office, the "
17395
+ "pre-shared key, the keepalive, and this computer's public key the one GEA has - and the text of the configuration, and refuses what is not one; its page waits, "
17396
+ "refuses a request without its own header or from a foreign origin, takes the zip as dropped, keeps the configuration owner-only and the log, and forgets; "
17397
+ "`wg show` is parsed; the self-test passes from the command line" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
17398
+ # -- EA2 the kits, the setup, the workflow, GEA's side -----------------------------------------------------------------------
17399
+ tools = pkg.parent / "tools"
17400
+ spec = _ilu.spec_from_file_location("gea_build_vpn", tools / "build_vpn.py")
17401
+ BV = _ilu.module_from_spec(spec); spec.loader.exec_module(BV)
17402
+ with __import__("contextlib").redirect_stdout(_io.StringIO()):
17403
+ tgz = BV.build_linux(d / "dist")
17404
+ with __import__("tarfile").open(tgz) as tf:
17405
+ names = sorted(n.split("/", 1)[1] for n in tf.getnames() if "/" in n)
17406
+ iss = (tools / "vpn_installer.iss").read_text(encoding="utf-8")
17407
+ wf = (pkg.parent / ".github" / "workflows" / "build-installer.yml").read_text(encoding="utf-8")
17408
+ marks = _re.findall(r'attach-kit\.sh "[^"]*" "([^"]+)" "([^"]+)"', wf)
17409
+ ico = IC.ico_bytes(kind="vpn")
17410
+ app_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
17411
+ c2 = {
17412
+ "kit": tgz.name == f"GEA-VPN-{__version__}.tar.gz" and {"install.sh", "README.md", "pyproject.toml", "SHA256SUMS.txt", "MANIFEST.json", "gea_vpn/__main__.py", "gea_vpn/service.py", "gea_vpn/wg.py", "gea_vpn/bundle.py"} <= set(names)
17413
+ and (any(n.startswith("gea_vpn-") and n.endswith(".whl") for n in names) or _ilu.find_spec("pip") is None) and "gea_vpn install" in (src / "install.sh").read_text(encoding="utf-8"),
17414
+ "setup": "5B7E2C1A-4D0F-4A7B-9C3E-2F6A8D1E7B42" in iss and "PrivilegesRequired=admin" in iss and "installtunnelservice" not in iss and "-m gea_vpn install" in iss and "wireguard-amd64-0.5.3.msi" in iss
17415
+ and "uninstall-service" in iss and "schtasks" in iss and "http://127.0.0.1:8795/" in iss,
17416
+ "workflow": "windows-vpn:" in wf and " vpn:" in wf and "build_vpn.py --win64" in wf and "WireGuard LLC" in wf and ("dist/GEA-VPN-Setup-*.exe", "GEA-VPN-Setup-") in marks
17417
+ and ("dist/GEA-VPN-*.tar.gz", "GEA-VPN-[0-9]") in marks and "/api/connect" in wf,
17418
+ "icon": len(ico) > 10000 and {s_ for s_, _, _, _ in IC.read_ico(ico)} >= {16, 32, 48, 256},
17419
+ "updates": "GEA-VPN-Setup-" in UP.KITS and "GEA-VPN-" in UP.KITS and UP.KITS.index("GEA-VPN-Setup-") < UP.KITS.index("GEA-VPN-"),
17420
+ "readme": "GEA-VPN-Setup-" in readme and "127.0.0.1:8795" in readme and "wireguard.com" in readme,
17421
+ "card": "GEA-VPN-Setup-" in app_src and "127.0.0.1:8795" in app_src,
17422
+ "help": not H.check("vpn") and "The client program" in (pkg / "help" / "vpn.md").read_text(encoding="utf-8") and "GEA-VPN-Setup-" in (pkg / "help" / "tutorial" / "23-vpn.md").read_text(encoding="utf-8")
17423
+ and "installtunnelservice" in (pkg / "help" / "IT_SECURITY.md").read_text(encoding="utf-8") and "vpn/" in (pkg.parent / "README.md").read_text(encoding="utf-8"),
17424
+ }
17425
+ failed2 = [k for k, v in c2.items() if not v]
17426
+ ok(not failed2,
17427
+ f"EA2 the Linux kit builds ({tgz.name}: the wheel, the program, install.sh, the sums) and its self-test passes on the built program; the Windows setup script installs "
17428
+ "as administrator, carries WireGuard's installer, registers the task and removes it; the workflow builds, signs, installs and attaches both kits with their marks; "
17429
+ "the icon has its sizes; the updates know the two kit names; the member's README, the card, the help, the tutorial and IT_SECURITY say so"
17430
+ + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
17431
+
17432
+
17283
17433
  def main() -> int:
17284
17434
  print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
17285
17435
  # a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
@@ -17413,6 +17563,7 @@ def main() -> int:
17413
17563
  section_dx_third_dimension(tmp)
17414
17564
  section_dy_vibration(tmp)
17415
17565
  section_dz_textbook_oracle(tmp)
17566
+ section_ea_vpn_client(tmp)
17416
17567
  if _FAILS:
17417
17568
  print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
17418
17569
  for f in _FAILS:
@@ -166,7 +166,21 @@ declared extras.
166
166
  admin-only and audited (`vpn.bundle.download`). The tunnel encrypts and
167
167
  addresses; the programs' own sign-in, roles and hashes apply through it
168
168
  unchanged, and the box's page is still bound to the pad network and the
169
- tunnel address only.
169
+ tunnel address only. The client program **GEA-VPN** (since 0.83.0, the
170
+ standalone kits `GEA-VPN-Setup-<v>.exe` and `GEA-VPN-<v>.tar.gz`) runs on
171
+ a member computer as a service - on Windows the scheduled task `GEA-VPN`
172
+ as SYSTEM, because `wireguard.exe /installtunnelservice` needs those
173
+ rights - and serves its page on 127.0.0.1:8795 only, to this computer's
174
+ own browser; its actions need a header a browser form of another site
175
+ cannot set, and a foreign Origin is refused. It keeps the member's
176
+ configuration (the private key) owner-only under `%ProgramData%\GEA-VPN`
177
+ (administrators and SYSTEM) or `/var/lib/gea-vpn` (root), shows the public
178
+ key only, and logs every connect, disconnect and forget with the name
179
+ given. It reaches no network itself: WireGuard does, as the configuration
180
+ says, and the page's one probe is a TCP connect to the office's port
181
+ through the tunnel. The Windows setup carries WireGuard's own installer,
182
+ whose Authenticode signature (WireGuard LLC) the build checks before the
183
+ setup is made; it is run only when the computer has no WireGuard.
170
184
  - **The tutorial** (since 0.76.0): the lessons are files inside the
171
185
  program; reading one writes nothing. A person's ticks are kept in the
172
186
  workspace (`records\tutorial_progress.json`, by account name, no more);
@@ -2,7 +2,7 @@
2
2
 
3
3
  > A program on the rig PC that reads the rig's own feed and the pre-drill model, places the bit in the layer with a position filter, and, every 30 ft, recommends in the driller's units what to do next - a policy trained by reinforcement learning in a physics twin of the lateral - with the driller's answer, every command, and the records pulled into GEA.
4
4
 
5
- **The command**: on the rig PC, `GEA-Driller-0.82.0.tar.gz` from the release (or the kit's `installers` folder, fetched on the Audit / Update tab): unpack it and run `sudo sh install.sh` on Linux or `install.cmd` on Windows, once; edit its config - the EDR's WITS0 feed (`tcp`, the host and port; `serial`, the COM port), the pre-drill model (the target layer's top TVD at the heel, its thickness and dip, the gamma in, above and below, the deep-resistivity tool, the heel's MD and TVD), the tool's cap, the limits - and restart it. The driller's screen is at port 8790 of the rig PC: `http://192.168.1.60:8790/live`. It shows the section with the model's layer window, the hole drilled through it and - since 0.78.0 - the **position filter**'s band: where the layer is from the readings, as a geosteerer places it (a particle filter over the layer's offset from the model, its dip error and its thickness, moved every decision and kept to the guesses that explain the gamma and the deep-resistivity distance), with the probability the bit is in the layer, above or below it and the distance to the top and the base with its spread, sixty feet ahead; the agent reads the same estimate, and so does the textbook driller it is judged against. Then the recommendation in words - *Build +1.5°/100 ft (toolface up, 25% steering); 25 klb WOB, 120 rpm, 500 gpm* - with its reasons (what the deep-resistivity tool says, the gamma against the model's values, the model's bracket, the limits) and the confidence of each choice, the rig's numbers against the limits, and **Accept**, **Reject** or **Did something else…** with the operator's name. In GEA: the **Drill string** tab's card **GEA Driller** - the rig PC's address and the well, **Pull**: the records come in checked against their hashes, and the table says how many decisions, accepted, rejected, done otherwise, the hole under advice, the armed sections and the commands. **Open the driller's screen** opens the rig PC's screen from its address. Before there is a rig PC: **Start the twin as the rig** runs the driller's program on this computer with a scene drilling itself under the agent - **Open its screen** is the driller's screen with the twin behind it, labelled SIMULATION - and **Pull from it** brings its records in; **Stop it** closes them. **Shadow a drilled well** (since 0.79.0): a well of this workspace with a drilling-recorder export is replayed through the advisor - every 30 ft the agent sees what the rig had shown to that point and nothing past it, and its recommendation is set beside what the record did next: the build actually made over the following 90 ft, the weight, speed and flow used, and at each stretch the gamma marks as out of the layer, whether the advisor called the way back at the first reading. The report, **SHADOW MODE**, is under the well's reports with a drawing of the lateral against the layer; the layer model is read off the well's own gamma in hindsight and says so - and grades how well it fits the well (good, fair, poor: a well steered to a rock that is not the low gamma reads poor, and the agent's calls against a poor model mean little) - unless the site's pre-drill model is given: a file `wells\Well-30636033\driller\model.json` with the config's `model` block (the target layer's top TVD at the heel, its thickness and dip, the gamma in, above and below, the heel's MD and TVD) is used whenever it is there (`gea workspace --path C:\site --action driller-shadow --well Well-30636033`). The export is read on this computer and nothing of it leaves it. Agreement with the driller says the two would have done alike, not that either was right. **The third dimension** (since 0.80.0): the lateral has an azimuth. The config's model carries the plan's azimuth (`plan_azimuth_deg`; empty, the first survey's at the heel is taken), the layer's dip across the plan line (`cross_dip_deg`, positive deepening to the right), the corridor the hole may run in to the right and left of the plan line (`corridor_ft`, the lease line and the offset wells) and where the heel sits across it (`heel_offset_ft`); the feed's surveys and the continuous azimuth (WITS item 0832, or the config's mapping) place the bit by minimum curvature along the plan, right of its line and in depth, and the screen draws the plan view - the corridor as a band, the hole against the plan line - under the section. The recommendation gains the aim - where to point the azimuth, along the plan or 4° left or right of it, and the turn that asks from where the hole points: *Build +1.5°/100 ft and aim 4° right of the plan (azimuth 44.0°), turning right 2.0°/100 ft (toolface 53°, 42% steering)* - with the build and the turn held together inside the DLS limit, and **Did something else…** takes the aim, or the turn made instead; the position filter carries the cross dip and reads it only when the hole moves across the plan line, leaving the model's value standing until then. In the twin the layer is a surface, the faults have a strike, the tool walks, and a hole that leaves the corridor by 150 ft is lost; the agent is judged on the hole in the corridor as well as in the layer (`gea-driller evaluate` prints both). Shadow mode reads the record's `azimuth_deg` column when it has one and sets the turn the advisor would have asked beside the turn the record made; without it the record's turns are not judged, and the report says so. **The vibration index from the feed** (since 0.81.0): a rig without a downhole vibration tool left the agent blind to the stick-slip and the whirl it was trained to ease, and the closed loop's vibration limit could never trip. Now the rig PC reads an index off the surface channels every EDR sends: over the last minute (`rig.vibration_window_s`), the surface torque's RMS about its mean as a fraction of the mean - the measure the Drill string page calls the oscillation index - times root two for the amplitude, and the same of the weight on bit and the hook load; stick-slip is the torque amplitude over 0.4, lateral vibration the weight amplitude over 0.2 (the twin's scale, where 1.2 is the limit), and the index is the larger. The downhole tool's item (WITS 0830) is taken instead whenever it comes, and every decision records which it read: the tile on the screen says *downhole tool* or *from surface data, stick-slip*, the reasons say *vibration 1.35 derived from the surface data (stick-slip, the surface torque swinging ±54%) over the limit 1.2*, and the limit disarms the loop on either. A surface proxy, labelled; on the twin as the rig it tracks the twin's own index within a few hundredths. The lateral file GEA writes for shadow mode carries, per foot, the surface channels' mean and RMS over the seconds of that foot (`torque_mean`, `torque_rms`, `wob_mean`, `wob_rms`, `hkld_mean`, `hkld_rms`, `rpm_mean`, `rpm_rms`, `spp_mean`, `spp_rms`), the replay reads the index off them for every decision, and the report says how often it stood over the limit and how often the advisor asked for less weight or more speed there than the record used; a record without torque or weight statistics says so and the advisor sees none. **The bar and the ceiling** (since 0.82.0): the agent is judged between two drillers on the same held-out scenes. The textbook driller is the bar - what a careful directional driller and geosteerer do by the book from the same observation the agent gets and nothing more: aim at the middle of the layer as the filter places it, steer back hard when the filter says the bit is out, lean away from a boundary the gamma's trend is running at, the rated weight in a calm hole in the layer and not while the hole fills, over the vibration limit lighter and faster first and heavier and slower when that did not quiet it, circulate at 40% of a bed, ream a balled bit, hold the plan line; it has a driller's memory of its own last decisions and none of the twin's secret. The oracle is the ceiling - the same driller told the twin's own layer at the bit and 120 ft ahead of it, which no policy can beat because it sees what no tool measures. `gea-driller evaluate` prints the three rows and how far the agent stands from the bar toward the ceiling; the self-test refuses a policy that does not beat the textbook, and the gate holds it under the oracle. The figures are a simulation's, labelled; a stronger textbook lowers the agent's standing without changing the agent, and that is the point of it. Over a cellular modem the rig PC joins GEA-VPN as a member of kind `driller` and GEA pulls from `http://10.77.0.4:8790`. The closed loop: `closed_loop.allowed` in the rig PC's config puts the switch on its screen; an operator arms it by name for one section of at most 500 ft (**Arm for this section**), every decision then goes to the downlink as a command, and the loop disarms itself on a stale feed, a crossed limit, the section's end or **Disarm now** - and this version's only downlink is the null one, which keeps every command on record and sends none, because no vendor's downlink protocol ships with it. From a terminal: `gea workspace --path C:\site --action driller-pull --box http://192.168.1.60:8790 --well SWD-1`; on the rig PC `gea-driller sim --seed 7 --pace 3 --port 8790`, `gea-driller evaluate --scenes 20`, `gea-driller train --seconds 600 --out policy.json`, `gea-driller selftest`.
5
+ **The command**: on the rig PC, `GEA-Driller-0.83.1.tar.gz` from the release (or the kit's `installers` folder, fetched on the Audit / Update tab): unpack it and run `sudo sh install.sh` on Linux or `install.cmd` on Windows, once; edit its config - the EDR's WITS0 feed (`tcp`, the host and port; `serial`, the COM port), the pre-drill model (the target layer's top TVD at the heel, its thickness and dip, the gamma in, above and below, the deep-resistivity tool, the heel's MD and TVD), the tool's cap, the limits - and restart it. The driller's screen is at port 8790 of the rig PC: `http://192.168.1.60:8790/live`. It shows the section with the model's layer window, the hole drilled through it and - since 0.78.0 - the **position filter**'s band: where the layer is from the readings, as a geosteerer places it (a particle filter over the layer's offset from the model, its dip error and its thickness, moved every decision and kept to the guesses that explain the gamma and the deep-resistivity distance), with the probability the bit is in the layer, above or below it and the distance to the top and the base with its spread, sixty feet ahead; the agent reads the same estimate, and so does the textbook driller it is judged against. Then the recommendation in words - *Build +1.5°/100 ft (toolface up, 25% steering); 25 klb WOB, 120 rpm, 500 gpm* - with its reasons (what the deep-resistivity tool says, the gamma against the model's values, the model's bracket, the limits) and the confidence of each choice, the rig's numbers against the limits, and **Accept**, **Reject** or **Did something else…** with the operator's name. In GEA: the **Drill string** tab's card **GEA Driller** - the rig PC's address and the well, **Pull**: the records come in checked against their hashes, and the table says how many decisions, accepted, rejected, done otherwise, the hole under advice, the armed sections and the commands. **Open the driller's screen** opens the rig PC's screen from its address. Before there is a rig PC: **Start the twin as the rig** runs the driller's program on this computer with a scene drilling itself under the agent - **Open its screen** is the driller's screen with the twin behind it, labelled SIMULATION - and **Pull from it** brings its records in; **Stop it** closes them. **Shadow a drilled well** (since 0.79.0): a well of this workspace with a drilling-recorder export is replayed through the advisor - every 30 ft the agent sees what the rig had shown to that point and nothing past it, and its recommendation is set beside what the record did next: the build actually made over the following 90 ft, the weight, speed and flow used, and at each stretch the gamma marks as out of the layer, whether the advisor called the way back at the first reading. The report, **SHADOW MODE**, is under the well's reports with a drawing of the lateral against the layer; the layer model is read off the well's own gamma in hindsight and says so - and grades how well it fits the well (good, fair, poor: a well steered to a rock that is not the low gamma reads poor, and the agent's calls against a poor model mean little) - unless the site's pre-drill model is given: a file `wells\Well-30636033\driller\model.json` with the config's `model` block (the target layer's top TVD at the heel, its thickness and dip, the gamma in, above and below, the heel's MD and TVD) is used whenever it is there (`gea workspace --path C:\site --action driller-shadow --well Well-30636033`). The export is read on this computer and nothing of it leaves it. Agreement with the driller says the two would have done alike, not that either was right. **The third dimension** (since 0.80.0): the lateral has an azimuth. The config's model carries the plan's azimuth (`plan_azimuth_deg`; empty, the first survey's at the heel is taken), the layer's dip across the plan line (`cross_dip_deg`, positive deepening to the right), the corridor the hole may run in to the right and left of the plan line (`corridor_ft`, the lease line and the offset wells) and where the heel sits across it (`heel_offset_ft`); the feed's surveys and the continuous azimuth (WITS item 0832, or the config's mapping) place the bit by minimum curvature along the plan, right of its line and in depth, and the screen draws the plan view - the corridor as a band, the hole against the plan line - under the section. The recommendation gains the aim - where to point the azimuth, along the plan or 4° left or right of it, and the turn that asks from where the hole points: *Build +1.5°/100 ft and aim 4° right of the plan (azimuth 44.0°), turning right 2.0°/100 ft (toolface 53°, 42% steering)* - with the build and the turn held together inside the DLS limit, and **Did something else…** takes the aim, or the turn made instead; the position filter carries the cross dip and reads it only when the hole moves across the plan line, leaving the model's value standing until then. In the twin the layer is a surface, the faults have a strike, the tool walks, and a hole that leaves the corridor by 150 ft is lost; the agent is judged on the hole in the corridor as well as in the layer (`gea-driller evaluate` prints both). Shadow mode reads the record's `azimuth_deg` column when it has one and sets the turn the advisor would have asked beside the turn the record made; without it the record's turns are not judged, and the report says so. **The vibration index from the feed** (since 0.81.0): a rig without a downhole vibration tool left the agent blind to the stick-slip and the whirl it was trained to ease, and the closed loop's vibration limit could never trip. Now the rig PC reads an index off the surface channels every EDR sends: over the last minute (`rig.vibration_window_s`), the surface torque's RMS about its mean as a fraction of the mean - the measure the Drill string page calls the oscillation index - times root two for the amplitude, and the same of the weight on bit and the hook load; stick-slip is the torque amplitude over 0.4, lateral vibration the weight amplitude over 0.2 (the twin's scale, where 1.2 is the limit), and the index is the larger. The downhole tool's item (WITS 0830) is taken instead whenever it comes, and every decision records which it read: the tile on the screen says *downhole tool* or *from surface data, stick-slip*, the reasons say *vibration 1.35 derived from the surface data (stick-slip, the surface torque swinging ±54%) over the limit 1.2*, and the limit disarms the loop on either. A surface proxy, labelled; on the twin as the rig it tracks the twin's own index within a few hundredths. The lateral file GEA writes for shadow mode carries, per foot, the surface channels' mean and RMS over the seconds of that foot (`torque_mean`, `torque_rms`, `wob_mean`, `wob_rms`, `hkld_mean`, `hkld_rms`, `rpm_mean`, `rpm_rms`, `spp_mean`, `spp_rms`), the replay reads the index off them for every decision, and the report says how often it stood over the limit and how often the advisor asked for less weight or more speed there than the record used; a record without torque or weight statistics says so and the advisor sees none. **The bar and the ceiling** (since 0.82.0): the agent is judged between two drillers on the same held-out scenes. The textbook driller is the bar - what a careful directional driller and geosteerer do by the book from the same observation the agent gets and nothing more: aim at the middle of the layer as the filter places it, steer back hard when the filter says the bit is out, lean away from a boundary the gamma's trend is running at, the rated weight in a calm hole in the layer and not while the hole fills, over the vibration limit lighter and faster first and heavier and slower when that did not quiet it, circulate at 40% of a bed, ream a balled bit, hold the plan line; it has a driller's memory of its own last decisions and none of the twin's secret. The oracle is the ceiling - the same driller told the twin's own layer at the bit and 120 ft ahead of it, which no policy can beat because it sees what no tool measures. `gea-driller evaluate` prints the three rows and how far the agent stands from the bar toward the ceiling; the self-test refuses a policy that does not beat the textbook, and the gate holds it under the oracle. The figures are a simulation's, labelled; a stronger textbook lowers the agent's standing without changing the agent, and that is the point of it. Over a cellular modem the rig PC joins GEA-VPN as a member of kind `driller` and GEA pulls from `http://10.77.0.4:8790`. The closed loop: `closed_loop.allowed` in the rig PC's config puts the switch on its screen; an operator arms it by name for one section of at most 500 ft (**Arm for this section**), every decision then goes to the downlink as a command, and the loop disarms itself on a stale feed, a crossed limit, the section's end or **Disarm now** - and this version's only downlink is the null one, which keeps every command on record and sends none, because no vendor's downlink protocol ships with it. From a terminal: `gea workspace --path C:\site --action driller-pull --box http://192.168.1.60:8790 --well SWD-1`; on the rig PC `gea-driller sim --seed 7 --pace 3 --port 8790`, `gea-driller evaluate --scenes 20`, `gea-driller train --seconds 600 --out policy.json`, `gea-driller selftest`.
6
6
 
7
7
  **What it writes**: on the rig PC, `decisions.jsonl` (every observation, recommendation, confidence, reasons and answer), `commands.jsonl` (every arming, command and disarming with its reason) and `surveys.csv`, each with a `.sha256` beside it, and `manifest.json`. In GEA, `wells\SWD-1\driller\` holds the same files as pulled, `manifest.json` and `last_pull.json` with the summary; the audit lines `driller.pull`, `driller.sim_start`, `driller.sim_stop`. The twin as the rig writes under `field\sim-driller\data`.
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > GEA-Program-Setup: the program installed for you like any Windows program - a window of its own, an icon in the notification area, Start-menu and desktop shortcuts, an Add/Remove Programs entry, upgrades in place - with no administrator rights and the site's data left where it is.
4
4
 
5
- **The command**: download the setup from the release on GitHub (`GEA-Program-Setup-0.82.0.exe` for this version) and run it. It installs for you alone, under `%LOCALAPPDATA%\Programs\GEA-Program`, and asks for the site workspace - the folder that holds the wells, reports, records, accounts and keys. An existing one such as `C:\site` is used exactly as it is, its name included; for a new one (by default `%LOCALAPPDATA%\GEA-Program\site`) it also asks the site's name, which heads every report, and makes the workspace with it (left empty, the workspace is named after its folder; an administrator renames the site in Administration's site settings). Then the Start menu's **GEA-Program** (and the desktop shortcut) starts the control panel when it is not running and opens it in a window of its own. A newer setup installs over the older one: it stops the control panel, replaces the program, keeps the workspace and the choices made before. For a site's software deployment: `GEA-Program-Setup-0.82.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"` (`/SITENAME` names a workspace the setup makes; one that exists keeps its own name). From a terminal: `gea launch` does what the shortcut does, `gea launch --selftest` says what it would do, `gea tray --selftest` checks the icon.
5
+ **The command**: download the setup from the release on GitHub (`GEA-Program-Setup-0.83.1.exe` for this version) and run it. It installs for you alone, under `%LOCALAPPDATA%\Programs\GEA-Program`, and asks for the site workspace - the folder that holds the wells, reports, records, accounts and keys. An existing one such as `C:\site` is used exactly as it is, its name included; for a new one (by default `%LOCALAPPDATA%\GEA-Program\site`) it also asks the site's name, which heads every report, and makes the workspace with it (left empty, the workspace is named after its folder; an administrator renames the site in Administration's site settings). Then the Start menu's **GEA-Program** (and the desktop shortcut) starts the control panel when it is not running and opens it in a window of its own. A newer setup installs over the older one: it stops the control panel, replaces the program, keeps the workspace and the choices made before. For a site's software deployment: `GEA-Program-Setup-0.83.1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"` (`/SITENAME` names a workspace the setup makes; one that exists keeps its own name). From a terminal: `gea launch` does what the shortcut does, `gea launch --selftest` says what it would do, `gea tray --selftest` checks the icon.
6
6
 
7
7
  **The window**: Microsoft Edge's app window (`msedge --app=`: the control panel with no tabs and no address bar, its own button on the taskbar, which shows the program's derrick and pins as GEA-Program, not as Edge), with a browser profile of its own (`%LOCALAPPDATA%\GEA-Program\window`, no extensions; the first time, Edge may say it signed that profile in to your Microsoft account - Got it), else Google Chrome's, else a tab in the default browser. Where the browser keeps no cookies (its settings or a policy block them), the sign-in page says so and the control panel holds the sign-in itself, in the window's address, until the window is closed. The control panel itself runs with no window of its own: `gea supervise` keeps it running in the background, starts it again when it asks for a restart, and writes everything it would have shown in a console - the start, the sign-ins, the jobs, a stop and why - to `records\console.log` in the workspace. No PowerShell or console window opens. The kit's `start-dashboard.cmd` still runs it in a console window, for a site that wants to watch it there.
8
8
 
@@ -18,7 +18,7 @@
18
18
 
19
19
  **The number to check**: Add/Remove Programs lists GEA-Program with the version you installed; `gea doctor --workspace C:\site` ends with `nothing blocks serving`; the Start menu's **Verify GEA-Program** runs the acceptance gate from the installation and ends with `[ACCEPTANCE] OK - N checks passed`. The release's build installs, upgrades and uninstalls the setup silently before it is published, with the control panel running, and checks the workspace untouched afterwards.
20
20
 
21
- **Signed**: when the publisher's code-signing certificate is configured for the build, the setup is signed with it (Authenticode, timestamped) and Windows names the publisher; until then it ships unsigned and Windows SmartScreen says "unknown publisher" (More info, then Run anyway). The build's provenance holds either way: `gh attestation verify GEA-Program-Setup-0.82.0.exe -R Daniel8Murphy0007/GEA-Program`. The uninstaller the setup leaves behind is Inno Setup's own and is not signed separately.
21
+ **Signed**: when the publisher's code-signing certificate is configured for the build, the setup is signed with it (Authenticode, timestamped) and Windows names the publisher; until then it ships unsigned and Windows SmartScreen says "unknown publisher" (More info, then Run anyway). The build's provenance holds either way: `gh attestation verify GEA-Program-Setup-0.83.1.exe -R Daniel8Murphy0007/GEA-Program`. The uninstaller the setup leaves behind is Inno Setup's own and is not signed separately.
22
22
 
23
23
  **What this page will not call a measurement**: the icon's running or stopped is whether the control panel's port answers on this computer, read every three seconds - not whether every patch, job or report behind it is healthy (Home and the Verification page say that).
24
24
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  **The command**: Reports tab -> Signed dossiers -> **Download GEA Reader for your clients**, or `gea reader --workspace C:\site --out C:\site\GEA-Reader.html`. Send the file once, by any channel (email, a USB stick, the client's portal); send the site's key fingerprint separately - by phone, email or in the contract - as for any dossier. The client opens GEA-Reader.html, drops a dossier on it (or chooses it), and reads the verdict: **Valid** (signed with the site's key, or with a newer key the site's key handed over to), **Valid, but signed by a key you were not given**, or **Not valid** with the reason. Below the verdict: each check, the signer's fingerprint, the key hand-overs, and every file the dossier holds - a report opens in the page as it was signed, a PDF in the browser's own viewer, a table or a log as text, and any file can be saved. A dossier that lists source records by hash without carrying them lets the client choose their copies and checks each against its hash.
6
6
 
7
- **The program**: for a client who wants it installed, **GEA-Reader-Setup-0.82.0.exe** on the release page installs GEA Reader as a Windows program of its own, for the signed-in user, with no administrator rights and nothing of GEA-Program: GEA Reader in the Start menu and on the desktop with its own icon (a white page with a green seal, on blue) and its own taskbar button, and **Check with GEA Reader** on the right-click menu of .zip files (on Windows 11, under Show more options), which opens the dossier at once. It opens the same page in Microsoft Edge's app window with a browser profile of its own (`%LOCALAPPDATA%\GEA-Reader\window`), so a fingerprint the client saves - **Remember this fingerprint**, with whose it is - stays on that computer, and every later dossier signed with that key reads **Valid** with the name the client gave it. `GEA-Reader-portable-0.82.0.zip` is the same program to unzip and run (`GEA-Reader.cmd`). `python\python.exe -m gea_reader --selftest`, in the installed folder, checks the page, the icon, the taskbar identity and the hand-over of a dossier without opening a window.
7
+ **The program**: for a client who wants it installed, **GEA-Reader-Setup-0.83.1.exe** on the release page installs GEA Reader as a Windows program of its own, for the signed-in user, with no administrator rights and nothing of GEA-Program: GEA Reader in the Start menu and on the desktop with its own icon (a white page with a green seal, on blue) and its own taskbar button, and **Check with GEA Reader** on the right-click menu of .zip files (on Windows 11, under Show more options), which opens the dossier at once. It opens the same page in Microsoft Edge's app window with a browser profile of its own (`%LOCALAPPDATA%\GEA-Reader\window`), so a fingerprint the client saves - **Remember this fingerprint**, with whose it is - stays on that computer, and every later dossier signed with that key reads **Valid** with the name the client gave it. `GEA-Reader-portable-0.83.1.zip` is the same program to unzip and run (`GEA-Reader.cmd`). `python\python.exe -m gea_reader --selftest`, in the installed folder, checks the page, the icon, the taskbar identity and the hand-over of a dossier without opening a window.
8
8
 
9
9
  **What it writes**: the one file, GEA-Reader.html (about 40 KB): the checks, written in the page's own script - Ed25519 (RFC 8032) in its own arithmetic, SHA-256 from the browser - and, when made from a workspace, the site's name and the fingerprints of every key it has signed with (the current one and each retired one from the key history: public halves only; the signing key never leaves `keys\`). The audit log records each download (`reader.download`) and each `gea reader` (`reader.write`) with the fingerprints the reader carried. The reader page writes nothing on the client's computer but the fingerprints a client saves (in the browser's storage for the page): it reads the zip it is given, in memory, and a saved copy goes where the client's browser saves downloads. The installed program also writes the page it opens to `%LOCALAPPDATA%\GEA-Reader\page` (with the dossier inside it when one was right-clicked; removed ten minutes later) and its right-click entry under the user's own registry keys, removed with the program.
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > GEA Recorder is the program on the pad: a Raspberry Pi in a sealed box that records the ground channels (geophones, accelerometers, electrode dipoles) through a 24-bit ADC and the rig's WITS0 feed, every sample on one GPS-disciplined clock, into hourly miniSEED files with a SHA-256 beside each and a manifest, and serves one status page on the pad network. Nothing to type: power it and it records. GEA pulls its files in and makes stations of them.
4
4
 
5
- **The command**: the **Seismic** tab, the card **Field recorder**: the box's address on the pad network (`http://192.168.1.50:8780` - the status page shows the address) or the folder of the USB mirror carried to the office, a station name if the site's is not wanted, then **Pull** (a job). GEA fetches the manifest, downloads every file it does not have, checks each against its SHA-256, and makes or updates two stations: the array of the ground-motion sensors (band 8-80 Hz, the sensors' positions from the box's config) and the electrode station (0.01-5 Hz); each sensor's hours are joined in order into one record, nothing re-sampled or filtered. Pull again later: only the new hours come across, and the stations are updated in place. From a terminal: `gea workspace --path C:\site --action field-pull --box http://192.168.1.50:8780`. On the box: `gea-recorder status`, `gea-recorder selftest`; `sudo sh kiosk.sh` once puts the live view full-screen on a monitor on the box's HDMI port from boot - RECORDING in green or what is wrong in red, the clock, the rig's depth, every channel's last minute and the ground sensors' spectrogram, nothing to press - and the same view is at `/live` on the box's page from any browser on the pad network; `sudo sh install.sh` once, from the release's `GEA-Recorder-0.82.0.tar.gz`; the box's README has the parts list, the wiring and the three chrony lines for the GPS clock.
5
+ **The command**: the **Seismic** tab, the card **Field recorder**: the box's address on the pad network (`http://192.168.1.50:8780` - the status page shows the address) or the folder of the USB mirror carried to the office, a station name if the site's is not wanted, then **Pull** (a job). GEA fetches the manifest, downloads every file it does not have, checks each against its SHA-256, and makes or updates two stations: the array of the ground-motion sensors (band 8-80 Hz, the sensors' positions from the box's config) and the electrode station (0.01-5 Hz); each sensor's hours are joined in order into one record, nothing re-sampled or filtered. Pull again later: only the new hours come across, and the stations are updated in place. From a terminal: `gea workspace --path C:\site --action field-pull --box http://192.168.1.50:8780`. On the box: `gea-recorder status`, `gea-recorder selftest`; `sudo sh kiosk.sh` once puts the live view full-screen on a monitor on the box's HDMI port from boot - RECORDING in green or what is wrong in red, the clock, the rig's depth, every channel's last minute and the ground sensors' spectrogram, nothing to press - and the same view is at `/live` on the box's page from any browser on the pad network; `sudo sh install.sh` once, from the release's `GEA-Recorder-0.83.1.tar.gz`; the box's README has the parts list, the wiring and the three chrony lines for the GPS clock.
6
6
 
7
7
  **Before there is a Pi**: on the same card, **Start the simulated box**: the recorder's own program runs on this computer with its test signal in place of the ADC (a process of its own, its files under `field\sim-box\` in the workspace, its page on port 8781), **Open its monitor** shows the live screen the attendant will see, **Pull from it** brings its files in as stations, **Stop it** closes every file and lists them. **Open the box's monitor** opens any real box's live screen from its address. The kit and the setup install the recorder's program beside GEA for this; a pip install adds it with `pip install gea-recorder`. **From the office, over the internet**: GEA-VPN (`gea help vpn`, Administration) gives every box a private address the office pulls from (`http://10.77.0.3:8780`) through a tunnel from the pad's cellular modem; the box's zip from that card holds `vpn.sh`, run once on the Pi.
8
8
 
@@ -5,10 +5,10 @@ Takes: 15 minutes
5
5
  > The program installed like any Windows program, with the site's folder chosen once.
6
6
 
7
7
  ## Before you start
8
- You need a Windows PC that will stay on while the site is watched (the office machine, or the doghouse PC), and the setup file for this version, `GEA-Program-Setup-0.82.0.exe`, from the release page on GitHub. No administrator rights are needed: the program installs for you alone.
8
+ You need a Windows PC that will stay on while the site is watched (the office machine, or the doghouse PC), and the setup file for this version, `GEA-Program-Setup-0.83.1.exe`, from the release page on GitHub. No administrator rights are needed: the program installs for you alone.
9
9
 
10
10
  ## Steps
11
- 1. Double-click `GEA-Program-Setup-0.82.0.exe`. If Windows asks whether to run it, choose **Run** - the setup is published by the site, not by a store.
11
+ 1. Double-click `GEA-Program-Setup-0.83.1.exe`. If Windows asks whether to run it, choose **Run** - the setup is published by the site, not by a store.
12
12
  2. The setup asks for the **site workspace**: the one folder that will hold the wells, the reports, the records, the accounts and the keys. For a new site keep the default or type `C:\site`. For a workspace that already exists, point at it - it is used exactly as it is, its name included.
13
13
  3. For a new workspace it asks the **site's name** (`Pad 3`). This name heads every report the program writes; an administrator can change it later in Administration, site settings.
14
14
  4. Tick the desktop shortcut and finish. The setup puts **GEA-Program** in the Start menu and an icon in the notification area by the clock.
@@ -8,7 +8,7 @@ Takes: 20 minutes
8
8
  1. On **Reports**, **Signed dossiers**: **Sign a dossier for the pad**, or one of the wells (the operator role). Tick *embed the source records* to carry the drilling records themselves rather than their hashes. The dossier is a zip: the reports as they stand, the declarations behind them, the audit log, the source records' hashes, the site's Ed25519 signature, and a checker inside (`verify_dossier.py`, plain Python).
9
9
  2. **Check** re-checks a dossier this site signed against the workspace as it now stands; a workspace that no longer matches a signed dossier raises an alert. *Check a dossier someone sent you* checks an uploaded one.
10
10
  3. **Download GEA Reader for your clients**: one HTML file. Send it to the client once by any channel - email, a USB stick, their portal. Send the site's **key fingerprint** separately - by phone, or in the contract - as for any dossier; the card shows it.
11
- 4. The client opens `GEA-Reader.html` in any current browser, offline, and drops a dossier on it. The verdict: **Valid** (signed with the site's key, or a newer key the site's key handed over to), **Valid, but signed by a key you were not given**, or **Not valid** with the reason. Below it, every file the dossier holds: a report opens in the page as it was signed, a PDF in the browser's own viewer. A client who wants it installed, with a right-click **Check with GEA Reader** on dossiers, gets `GEA-Reader-Setup-0.82.0.exe` from the release page.
11
+ 4. The client opens `GEA-Reader.html` in any current browser, offline, and drops a dossier on it. The verdict: **Valid** (signed with the site's key, or a newer key the site's key handed over to), **Valid, but signed by a key you were not given**, or **Not valid** with the reason. Below it, every file the dossier holds: a report opens in the page as it was signed, a PDF in the browser's own viewer. A client who wants it installed, with a right-click **Check with GEA Reader** on dossiers, gets `GEA-Reader-Setup-0.83.1.exe` from the release page.
12
12
  5. **The key**: it lives in `keys\dossier_ed25519.json` in the workspace. The backup carries it; nothing else does; never send it. An administrator **rotates** it with a reason when a person who had access leaves; the old key's history rides in every later dossier so a reader of an old dossier still knows it was the site's.
13
13
 
14
14
  ## You know it worked when
@@ -8,7 +8,7 @@ Takes: 10 minutes
8
8
  1. Open **Audit / Update**, the card **The release**: the newest release on GitHub against the version running, with the three kits it carries - `GEA-Program-Setup`, `GEA-Reader-Setup` and `GEA-Recorder` - each with the SHA-256 GitHub recorded.
9
9
  2. Press **Fetch the kits** (the button names the version). A job brings them into the workspace's `installers\` folder, checks each against its recorded hash (a kit altered after that is not kept), and moves older kits to `installers\_older`. The card marks every kit on hand ✓.
10
10
  3. Press **Install now** (the button names the version). The program's setup runs silently from there with this workspace, and the reader's setup with it; the control panel stops for about a minute and is started again by a helper outside the program. Sign in again. The card now shows the new version running.
11
- 4. The recorder's kit, `GEA-Recorder-0.82.0.tar.gz`, is in the same folder for the attendant to take to the box (lesson 25).
11
+ 4. The recorder's kit, `GEA-Recorder-0.83.1.tar.gz`, is in the same folder for the attendant to take to the box (lesson 25); so are the driller's, `GEA-Driller-0.83.1.tar.gz` (lesson 29), and GEA-VPN's two, `GEA-VPN-Setup-0.83.1.exe` and `GEA-VPN-0.83.1.tar.gz`, for every computer that joins the private network (lesson 23).
12
12
  5. On a computer that cannot reach GitHub, the setup from the release page installs over the old version the same way; the workspace is kept.
13
13
 
14
14
  ## You know it worked when
@@ -12,7 +12,7 @@ One **hub**: a small cloud server of the site's own - any Debian or Ubuntu machi
12
12
  2. Download **gea-vpn-hub.zip**, copy it to the hub and run there, once: `sudo sh install-hub.sh`. It installs WireGuard, opens the port, turns forwarding on and starts the tunnel at boot.
13
13
  3. On this PC: open WireGuard, **Import tunnel(s) from file**, choose `gea-vpn.conf` from **gea-vpn-office.zip**, **Activate**. The card's pill turns to **tunnel up**.
14
14
  4. Add a member per computer: its name (`Pad 3 box`) and its kind - **box** for a recorder (reaches the office only), **operator** or **reader** for a window (reaches the office's control panel only), **office** for a second control panel - then **Add the member**. Its address and its zip appear in the table. Run the hub installer again - the hub's folder is written anew with every member.
15
- 5. Hand each member its zip by a channel of its own - in person, or not by the same e-mail as anything else: it holds that computer's key. A box: `sudo sh vpn.sh` on the Pi, once (lesson 27). A Windows member imports its `gea-vpn.conf` into WireGuard, once.
15
+ 5. Hand each member its zip by a channel of its own - in person, or not by the same e-mail as anything else: it holds that computer's key. A box: `sudo sh vpn.sh` on the Pi, once (lesson 27). Every other member installs **GEA-VPN** once (`GEA-VPN-Setup-0.83.1.exe` on Windows, `GEA-VPN-0.83.1.tar.gz` on Linux, from the release or the office's `installers\` folder), opens it from the Start menu, drops its zip on the page and presses **Connect** - the page reads *connected* when the hub has answered, and says whether this office answers through the tunnel. (A Windows member without GEA-VPN imports its `gea-vpn.conf` into WireGuard by hand.)
16
16
  6. The table shows each member's **last handshake** (within two or three minutes means its tunnel is up) and whether its program **answers** through the tunnel. Pull from a box at its private address: `http://10.77.0.3:8780`.
17
17
  7. A lost file, or a computer that leaves: **Remove** the member and run the hub installer again; add it again for a new key. The keys are in `keys\vpn\network.json`, owner-only - the backup carries it, the dossier never does.
18
18
 
@@ -5,10 +5,10 @@ Takes: 30 minutes
5
5
  > One script, one config file, one restart.
6
6
 
7
7
  ## Before you start
8
- The box assembled (lesson 24), the Pi on the pad network, and the release's `GEA-Recorder-0.82.0.tar.gz` - from the office's `installers\` folder (lesson 22) or the release page - copied to the Pi.
8
+ The box assembled (lesson 24), the Pi on the pad network, and the release's `GEA-Recorder-0.83.1.tar.gz` - from the office's `installers\` folder (lesson 22) or the release page - copied to the Pi.
9
9
 
10
10
  ## Steps
11
- 1. On the Pi, unpack the kit and run the installer once: `tar xzf GEA-Recorder-0.82.0.tar.gz`, `cd GEA-Recorder-0.82.0`, `sudo sh install.sh`. It makes `/opt/gea-recorder` (a Python environment of its own), writes the example config to `/etc/gea-recorder/config.json`, makes `/var/lib/gea-recorder`, enables SPI, enables the service to start at boot and runs the self-test.
11
+ 1. On the Pi, unpack the kit and run the installer once: `tar xzf GEA-Recorder-0.83.1.tar.gz`, `cd GEA-Recorder-0.83.1`, `sudo sh install.sh`. It makes `/opt/gea-recorder` (a Python environment of its own), writes the example config to `/etc/gea-recorder/config.json`, makes `/var/lib/gea-recorder`, enables SPI, enables the service to start at boot and runs the self-test.
12
12
  2. The clock: wire the GPS as lesson 24 says, then the three lines the README gives - `dtoverlay=pps-gpio,gpiopin=18` and `enable_uart=1` in `/boot/firmware/config.txt`, the two `refclock` lines in `/etc/chrony/chrony.conf` - `sudo apt install gpsd pps-tools`, and reboot. `chronyc tracking` then names PPS as the reference with an offset of microseconds.
13
13
  3. Edit the config: `sudo nano /etc/gea-recorder/config.json`. The site's name as the office spells it; the station id; the wellhead's latitude and longitude; each channel's ADC input, its id (`REF`, `S01`...), its kind (`geophone` or `electrode`) and its place in feet east and north of the wellhead; the ADC driver `ads1256` (`sim` records a test signal with no hardware); the rig feed - `rig.enabled`, the serial port or the TCP host and port the EDR offers; the mirror path for the USB stick.
14
14
  4. `sudo systemctl restart gea-recorder`. Open the box's page from any computer on the pad network: port 8780 of the box's address - `http://192.168.1.50:8780/` when that is its address. It shows the site, the station, RECORDING, the clock and what its time is worth, every channel's level, the files closed, the free space, the rig feed.
@@ -5,7 +5,7 @@ Takes: 30 minutes
5
5
  > One install, one config file, and the driller's screen on the rig.
6
6
 
7
7
  ## Before you start
8
- The rig PC (the EDR's own, or the directional driller's laptop) on the rig network, with the EDR's WITS0 feed available on a TCP port or a serial line - ask the EDR vendor's hand for the port; it is read-only and nothing is ever sent to it. The kit `GEA-Driller-0.82.0.tar.gz` from the office's `installers\` folder (lesson 22) or the release page. On Windows, Python 3.9 or newer from python.org with "Add to PATH" ticked.
8
+ The rig PC (the EDR's own, or the directional driller's laptop) on the rig network, with the EDR's WITS0 feed available on a TCP port or a serial line - ask the EDR vendor's hand for the port; it is read-only and nothing is ever sent to it. The kit `GEA-Driller-0.83.1.tar.gz` from the office's `installers\` folder (lesson 22) or the release page. On Windows, Python 3.9 or newer from python.org with "Add to PATH" ticked.
9
9
 
10
10
  ## Steps
11
11
  1. Unpack the kit. On a Linux PC: `sudo sh install.sh`. On Windows: double-click `install.cmd`. Either makes a Python environment of its own with the package and the trained policy inside it, writes the example config beside it, makes the data folder, runs the self-test (a minute: the twin, the policy against the textbook driller, a short training that learns, the service), and sets the program to start with the PC.
@@ -2,9 +2,9 @@
2
2
 
3
3
  > Every step of GEA and the programs around it - the control panel, the Reader, the Recorder on the pad, GEA-VPN, GEA Driller - as 29 lessons: the office's first, the pad attendant's after, each naming the page it is done on, what you press, and how you know it worked.
4
4
 
5
- **The command**: the **Tutorial** tab. The lessons are listed by part - Getting started, Wells and their data, Watching the pad, The engineering pages, Seismic, Reports for the client, Keeping it running, On the pad, The driller's agent - each with who it is for and how long it takes. Open one: **Open the page this lesson is about** goes to the tab it is done on, the numbered steps say what to press, **You know it worked when** says what to look for, and **Mark this lesson done** ticks it off for you (each account has its own progress; the list says how many are done and which comes next). **Print the handout** opens the whole course as one page for the people who do not sit at this screen - the attendant on the pad - and the browser's Print makes the PDF; **Write the handout into exports\tutorial** (the operator role) writes the same as `GEA-Tutorial-0.82.0.html` and `.md` into the workspace. From a terminal: `gea tutorial` lists the lessons, `gea tutorial --lesson 3` prints one, `gea tutorial --lesson install` the same by name, `gea tutorial --handout --workspace C:\site` writes the handout into the workspace, `gea tutorial --handout --out C:\site\GEA-Tutorial.html` writes it anywhere. The lessons are Markdown files under the program's `help\tutorial` folder.
5
+ **The command**: the **Tutorial** tab. The lessons are listed by part - Getting started, Wells and their data, Watching the pad, The engineering pages, Seismic, Reports for the client, Keeping it running, On the pad, The driller's agent - each with who it is for and how long it takes. Open one: **Open the page this lesson is about** goes to the tab it is done on, the numbered steps say what to press, **You know it worked when** says what to look for, and **Mark this lesson done** ticks it off for you (each account has its own progress; the list says how many are done and which comes next). **Print the handout** opens the whole course as one page for the people who do not sit at this screen - the attendant on the pad - and the browser's Print makes the PDF; **Write the handout into exports\tutorial** (the operator role) writes the same as `GEA-Tutorial-0.83.1.html` and `.md` into the workspace. From a terminal: `gea tutorial` lists the lessons, `gea tutorial --lesson 3` prints one, `gea tutorial --lesson install` the same by name, `gea tutorial --handout --workspace C:\site` writes the handout into the workspace, `gea tutorial --handout --out C:\site\GEA-Tutorial.html` writes it anywhere. The lessons are Markdown files under the program's `help\tutorial` folder.
6
6
 
7
- **What it writes**: `records\tutorial_progress.json` in the workspace (who finished which lesson, when); `exports\tutorial\GEA-Tutorial-0.82.0.html` and `.md` when the handout is written, with the audit line `tutorial.handout`; `tutorial.print` when the handout is opened from the page. Reading a lesson writes nothing.
7
+ **What it writes**: `records\tutorial_progress.json` in the workspace (who finished which lesson, when); `exports\tutorial\GEA-Tutorial-0.83.1.html` and `.md` when the handout is written, with the audit line `tutorial.handout`; `tutorial.print` when the handout is opened from the page. Reading a lesson writes nothing.
8
8
 
9
9
  **The number to check**: the list's "done" count against 29, and on the Tutorial tab which lesson is next. A lesson's own check is its **You know it worked when** - the thing on the screen or the disk that is there only if the steps were done; a tick without it is a tick.
10
10
 
@@ -4,6 +4,8 @@
4
4
 
5
5
  **The command**: the Administration tab's **GEA-VPN** card (admin). It is WireGuard - the VPN built into every Linux kernel and installed on Windows from wireguard.com - and GEA writes every key, address and configuration, so nothing is typed on a pad. One **hub** is needed: a small cloud server of the site's own, any Debian or Ubuntu machine with a public address (a rented virtual server of the smallest size is enough), reachable on UDP port 51820; every member connects out to it and it forwards between the office and each member - members never see one another. Make the network once: enter the hub's public name or address (`vpn.pad3site.com` or `203.0.113.10`) and click **Make the network** - the office member (this control panel, `10.77.0.2`) is made with it. Download `gea-vpn-hub.zip`, copy it to the hub and run there, once, `sudo sh install-hub.sh` (it installs WireGuard, opens the port, turns forwarding on and starts the tunnel at boot). Install WireGuard on this computer from wireguard.com (admin, once), click **Import tunnel(s) from file**, choose `gea-vpn.conf` from `gea-vpn-office.zip`, click **Activate**; the card's pill turns to `tunnel up`. Add a member per computer: its name (`Pad 3 box`) and its kind - `box` for a recorder (its page on 8780, reaches the office only), `driller` for the driller's agent on a rig PC (its screen on 8790, reaches the office only), `operator` or `reader` for a window (reaches the office's control panel only), `office` for a second control panel - then **Add the member**; its address and `gea-vpn-pad-3-box.zip` appear in the table, and the hub installer must be run again (the hub's folder is written anew with every member). A box's zip holds `vpn.sh`: on the Pi, `sudo sh vpn.sh` once. A Windows member imports its `gea-vpn.conf` into WireGuard once. In the Field tab, pull from the box at its private address: `http://10.77.0.3:8780`. **Remove** takes a member out (its key is dropped from the hub when the installer runs again); **Make the files again** rewrites every folder and zip. From a terminal: `gea vpn --workspace C:\site --create vpn.pad3site.com`, `gea vpn --workspace C:\site --add "Pad 3 box" --kind box`, `gea vpn --workspace C:\site --remove pad-3-box`, `gea vpn --workspace C:\site --bundles`, `gea vpn --workspace C:\site` (the table).
6
6
 
7
+ **The client program** (since 0.83.0): every member but the hub and the Pi installs **GEA-VPN**, a standalone program of its own - `GEA-VPN-Setup-<version>.exe` on Windows (administrator rights, once: it installs WireGuard for Windows from the official installer it carries when the computer has none, and runs the program as a service of its own, the scheduled task `GEA-VPN` as SYSTEM at every start, because a tunnel service needs those rights and a person should not), `GEA-VPN-<version>.tar.gz` on Linux (`sudo sh install.sh`: WireGuard from the distribution, the service `gea-vpn` under systemd); both on every release and fetched into `installers\` with the other kits on Audit / Update. Installed, it is **ready for the connect information**: its page at `http://127.0.0.1:8795/` on that computer (the Start menu's **GEA-VPN**) waits for the member's zip - dropped on it, chosen, or the text of `gea-vpn.conf` pasted - checks it key by key, and on **Connect** brings the tunnel up now and at every start; from then on the page says whether WireGuard is installed, whether the tunnel is up, when the hub last answered (a handshake within three minutes means it is talking), the bytes each way, and whether this office answers through the tunnel. **Disconnect** takes the tunnel down; **Disconnect and forget** removes the connect information from the computer, and the office removes the member and makes a new zip. The page listens on 127.0.0.1 only and answers its own requests only; the connect information is kept owner-only under `%ProgramData%\GEA-VPN` (Windows, administrators) or `/var/lib/gea-vpn` (Linux, root) with a log of what was done, by whom. From a terminal on that computer: `gea-vpn status`, `gea-vpn connect gea-vpn-pad-3-rig-pc.zip`, `gea-vpn disconnect`, `gea-vpn forget`, `gea-vpn selftest`.
8
+
7
9
  **What it writes**: `keys\vpn\network.json` (owner-only; every member's private key, the hub's, and the pre-shared key per member) - the backup carries it, the dossier never does; under `exports\vpn\`: `hub\` (`gea-vpn.conf`, `install-hub.sh`, `README.txt`, zipped as `gea-vpn-hub.zip`) and one folder per member (`gea-vpn.conf` with the member's own private key, plus `vpn.sh` for a box or `README.txt` for a window, zipped as `gea-vpn-pad-3-box.zip` for `Pad 3 box`); the audit lines `vpn.create`, `vpn.hub`, `vpn.member.add`, `vpn.member.remove`, `vpn.bundles`, `vpn.bundle.download`. A member's zip holds its key: hand it over in person, or by a channel of its own, never by the same e-mail as anything else; a lost file is replaced by removing the member, adding it again and running the hub installer again.
8
10
 
9
11
  **The number to check**: the card's pill - `tunnel up` means WireGuard on this computer has the `gea-vpn` tunnel active; `tunnel not up here` means it is not installed or not activated, and nothing private is reachable. In the table, **Last handshake** within the last two or three minutes for a member means its tunnel is up and talking to this computer (a keepalive every 25 s keeps it so behind a cellular modem); **Reachable** `yes` means the member's program answered on its port through the tunnel - a box's page on 8780, a window's control panel - and that is the address to pull from.