gea-program 0.54.0__tar.gz → 0.56.0__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 (367) hide show
  1. {gea_program-0.54.0/gea_program.egg-info → gea_program-0.56.0}/PKG-INFO +48 -5
  2. {gea_program-0.54.0 → gea_program-0.56.0}/README.md +47 -4
  3. {gea_program-0.54.0 → gea_program-0.56.0}/gea/__init__.py +1 -1
  4. {gea_program-0.54.0 → gea_program-0.56.0}/gea/__main__.py +127 -3
  5. {gea_program-0.54.0 → gea_program-0.56.0}/gea/acceptance_tests.py +423 -0
  6. {gea_program-0.54.0 → gea_program-0.56.0}/gea/alerts.py +15 -2
  7. {gea_program-0.54.0 → gea_program-0.56.0}/gea/doctor.py +12 -0
  8. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/alerts.md +1 -1
  9. gea_program-0.56.0/gea/help/company-sign-in.md +19 -0
  10. gea_program-0.56.0/gea/help/https.md +19 -0
  11. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/upkeep.md +2 -2
  12. {gea_program-0.54.0 → gea_program-0.56.0}/gea/helplib.py +2 -0
  13. {gea_program-0.54.0 → gea_program-0.56.0}/gea/notify.py +3 -1
  14. gea_program-0.56.0/gea/oidc.py +379 -0
  15. gea_program-0.56.0/gea/oidc_mock.py +135 -0
  16. {gea_program-0.54.0 → gea_program-0.56.0}/gea/service.py +271 -10
  17. gea_program-0.56.0/gea/tls.py +530 -0
  18. {gea_program-0.54.0 → gea_program-0.56.0}/gea/web/app.html +45 -13
  19. {gea_program-0.54.0 → gea_program-0.56.0/gea_program.egg-info}/PKG-INFO +48 -5
  20. {gea_program-0.54.0 → gea_program-0.56.0}/gea_program.egg-info/SOURCES.txt +5 -0
  21. {gea_program-0.54.0 → gea_program-0.56.0}/pyproject.toml +1 -1
  22. {gea_program-0.54.0 → gea_program-0.56.0}/LICENSE +0 -0
  23. {gea_program-0.54.0 → gea_program-0.56.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  24. {gea_program-0.54.0 → gea_program-0.56.0}/gea/accuracy_statement.py +0 -0
  25. {gea_program-0.54.0 → gea_program-0.56.0}/gea/alarm_engine.py +0 -0
  26. {gea_program-0.54.0 → gea_program-0.56.0}/gea/backup.py +0 -0
  27. {gea_program-0.54.0 → gea_program-0.56.0}/gea/bench.py +0 -0
  28. {gea_program-0.54.0 → gea_program-0.56.0}/gea/blind_harness.py +0 -0
  29. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  30. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  31. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  32. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  33. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  34. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  35. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  36. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  37. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  38. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  39. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  40. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  41. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  42. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  43. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  44. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  45. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  46. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  47. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  48. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  49. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  50. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  51. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  52. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  53. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  54. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  55. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  56. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  57. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  58. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  59. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  60. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  61. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  62. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  63. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  64. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  65. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  66. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  67. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  68. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  69. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  70. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  71. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  72. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  73. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  74. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  75. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  76. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  77. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  78. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  79. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  80. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  81. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  82. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  83. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  84. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  85. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  86. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  87. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  88. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  89. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  90. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  91. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  92. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  93. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  94. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  95. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  96. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/med_160_sapropels.txt +0 -0
  97. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  98. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  99. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  100. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  101. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  102. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  103. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  104. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  105. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  106. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  107. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  108. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  109. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  110. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  111. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  112. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  113. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  114. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  115. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  116. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  117. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  118. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  119. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  120. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  121. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  122. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  123. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  124. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  125. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  126. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  127. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  128. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  129. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  130. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  131. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  132. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  133. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog_map.py +0 -0
  134. {gea_program-0.54.0 → gea_program-0.56.0}/gea/catalog_register.py +0 -0
  135. {gea_program-0.54.0 → gea_program-0.56.0}/gea/certificates.py +0 -0
  136. {gea_program-0.54.0 → gea_program-0.56.0}/gea/cli.py +0 -0
  137. {gea_program-0.54.0 → gea_program-0.56.0}/gea/client_reports.py +0 -0
  138. {gea_program-0.54.0 → gea_program-0.56.0}/gea/collision.py +0 -0
  139. {gea_program-0.54.0 → gea_program-0.56.0}/gea/config_versioning.py +0 -0
  140. {gea_program-0.54.0 → gea_program-0.56.0}/gea/conformance.py +0 -0
  141. {gea_program-0.54.0 → gea_program-0.56.0}/gea/control_room.py +0 -0
  142. {gea_program-0.54.0 → gea_program-0.56.0}/gea/correlation.py +0 -0
  143. {gea_program-0.54.0 → gea_program-0.56.0}/gea/dashboard.py +0 -0
  144. {gea_program-0.54.0 → gea_program-0.56.0}/gea/declarations.py +0 -0
  145. {gea_program-0.54.0 → gea_program-0.56.0}/gea/decline.py +0 -0
  146. {gea_program-0.54.0 → gea_program-0.56.0}/gea/deviation.py +0 -0
  147. {gea_program-0.54.0 → gea_program-0.56.0}/gea/dlis.py +0 -0
  148. {gea_program-0.54.0 → gea_program-0.56.0}/gea/dnp3.py +0 -0
  149. {gea_program-0.54.0 → gea_program-0.56.0}/gea/dossier.py +0 -0
  150. {gea_program-0.54.0 → gea_program-0.56.0}/gea/dossier_verify.py +0 -0
  151. {gea_program-0.54.0 → gea_program-0.56.0}/gea/downhole_engine.py +0 -0
  152. {gea_program-0.54.0 → gea_program-0.56.0}/gea/drift_monitor.py +0 -0
  153. {gea_program-0.54.0 → gea_program-0.56.0}/gea/drill_string.py +0 -0
  154. {gea_program-0.54.0 → gea_program-0.56.0}/gea/earth_model.py +0 -0
  155. {gea_program-0.54.0 → gea_program-0.56.0}/gea/economics.py +0 -0
  156. {gea_program-0.54.0 → gea_program-0.56.0}/gea/ed25519.py +0 -0
  157. {gea_program-0.54.0 → gea_program-0.56.0}/gea/edr.py +0 -0
  158. {gea_program-0.54.0 → gea_program-0.56.0}/gea/elevation.py +0 -0
  159. {gea_program-0.54.0 → gea_program-0.56.0}/gea/etp.py +0 -0
  160. {gea_program-0.54.0 → gea_program-0.56.0}/gea/etp12_schemas.json +0 -0
  161. {gea_program-0.54.0 → gea_program-0.56.0}/gea/example_register_map.json +0 -0
  162. {gea_program-0.54.0 → gea_program-0.56.0}/gea/fat_sat.py +0 -0
  163. {gea_program-0.54.0 → gea_program-0.56.0}/gea/files.py +0 -0
  164. {gea_program-0.54.0 → gea_program-0.56.0}/gea/fixtures/README.md +0 -0
  165. {gea_program-0.54.0 → gea_program-0.56.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
  166. {gea_program-0.54.0 → gea_program-0.56.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
  167. {gea_program-0.54.0 → gea_program-0.56.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
  168. {gea_program-0.54.0 → gea_program-0.56.0}/gea/fixtures/ne_110m_coastline.json +0 -0
  169. {gea_program-0.54.0 → gea_program-0.56.0}/gea/follower.py +0 -0
  170. {gea_program-0.54.0 → gea_program-0.56.0}/gea/forward_model.py +0 -0
  171. {gea_program-0.54.0 → gea_program-0.56.0}/gea/frac_hits.py +0 -0
  172. {gea_program-0.54.0 → gea_program-0.56.0}/gea/friction_priors.py +0 -0
  173. {gea_program-0.54.0 → gea_program-0.56.0}/gea/gamma.py +0 -0
  174. {gea_program-0.54.0 → gea_program-0.56.0}/gea/gauge_aging.py +0 -0
  175. {gea_program-0.54.0 → gea_program-0.56.0}/gea/gauge_specs.py +0 -0
  176. {gea_program-0.54.0 → gea_program-0.56.0}/gea/geodesy.py +0 -0
  177. {gea_program-0.54.0 → gea_program-0.56.0}/gea/geomag.py +0 -0
  178. {gea_program-0.54.0 → gea_program-0.56.0}/gea/gravity_reference.py +0 -0
  179. {gea_program-0.54.0 → gea_program-0.56.0}/gea/hartip.py +0 -0
  180. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/TESTER_GUIDE.md +0 -0
  181. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/alarms.md +0 -0
  182. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/audit-update.md +0 -0
  183. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/backup.md +0 -0
  184. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/catalog.md +0 -0
  185. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/charts.md +0 -0
  186. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/collision.md +0 -0
  187. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/conformance.md +0 -0
  188. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/control-room.md +0 -0
  189. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/data-in.md +0 -0
  190. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/declare.md +0 -0
  191. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/decline.md +0 -0
  192. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/dlis.md +0 -0
  193. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/doctor.md +0 -0
  194. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/dossier.md +0 -0
  195. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/drift.md +0 -0
  196. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/drillstring.md +0 -0
  197. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/economics.md +0 -0
  198. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/edr.md +0 -0
  199. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/etp.md +0 -0
  200. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/field-ports.md +0 -0
  201. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/files.md +0 -0
  202. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/frac-hits.md +0 -0
  203. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/historian.md +0 -0
  204. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/instruments.md +0 -0
  205. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/interval.md +0 -0
  206. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/invoice-check.md +0 -0
  207. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/map.md +0 -0
  208. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/month-end.md +0 -0
  209. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/notifications.md +0 -0
  210. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/opseis.md +0 -0
  211. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/osdu.md +0 -0
  212. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/pad-summary.md +0 -0
  213. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/patches.md +0 -0
  214. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/penetrator.md +0 -0
  215. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/plan.md +0 -0
  216. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/pore-pressure.md +0 -0
  217. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/ppdm.md +0 -0
  218. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/quakeml.md +0 -0
  219. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/quality.md +0 -0
  220. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/report-history.md +0 -0
  221. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/rig-time.md +0 -0
  222. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/seedlink.md +0 -0
  223. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/seismic.md +0 -0
  224. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/setup.md +0 -0
  225. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/simulation.md +0 -0
  226. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/site.md +0 -0
  227. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/sites.md +0 -0
  228. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/slip.md +0 -0
  229. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/soak.md +0 -0
  230. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/sra.md +0 -0
  231. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/start.md +0 -0
  232. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/structure.md +0 -0
  233. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/tools.md +0 -0
  234. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/torque-drag.md +0 -0
  235. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/transients.md +0 -0
  236. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/vibration.md +0 -0
  237. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/well-report.md +0 -0
  238. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/well-tests.md +0 -0
  239. {gea_program-0.54.0 → gea_program-0.56.0}/gea/help/well3d.md +0 -0
  240. {gea_program-0.54.0 → gea_program-0.56.0}/gea/housekeeping.py +0 -0
  241. {gea_program-0.54.0 → gea_program-0.56.0}/gea/interval.py +0 -0
  242. {gea_program-0.54.0 → gea_program-0.56.0}/gea/inverse_engine.py +0 -0
  243. {gea_program-0.54.0 → gea_program-0.56.0}/gea/invoice_check.py +0 -0
  244. {gea_program-0.54.0 → gea_program-0.56.0}/gea/jobs.py +0 -0
  245. {gea_program-0.54.0 → gea_program-0.56.0}/gea/live_ports.py +0 -0
  246. {gea_program-0.54.0 → gea_program-0.56.0}/gea/loadtest.py +0 -0
  247. {gea_program-0.54.0 → gea_program-0.56.0}/gea/matplotlib_demo.py +0 -0
  248. {gea_program-0.54.0 → gea_program-0.56.0}/gea/modbus.py +0 -0
  249. {gea_program-0.54.0 → gea_program-0.56.0}/gea/modbus_rtu.py +0 -0
  250. {gea_program-0.54.0 → gea_program-0.56.0}/gea/model_card.py +0 -0
  251. {gea_program-0.54.0 → gea_program-0.56.0}/gea/month_end.py +0 -0
  252. {gea_program-0.54.0 → gea_program-0.56.0}/gea/mqtt_port.py +0 -0
  253. {gea_program-0.54.0 → gea_program-0.56.0}/gea/op_seismicity.py +0 -0
  254. {gea_program-0.54.0 → gea_program-0.56.0}/gea/opcua_port.py +0 -0
  255. {gea_program-0.54.0 → gea_program-0.56.0}/gea/operator_app.py +0 -0
  256. {gea_program-0.54.0 → gea_program-0.56.0}/gea/osdu.py +0 -0
  257. {gea_program-0.54.0 → gea_program-0.56.0}/gea/pad_summary.py +0 -0
  258. {gea_program-0.54.0 → gea_program-0.56.0}/gea/patches.py +0 -0
  259. {gea_program-0.54.0 → gea_program-0.56.0}/gea/pdf_report.py +0 -0
  260. {gea_program-0.54.0 → gea_program-0.56.0}/gea/penetrator.py +0 -0
  261. {gea_program-0.54.0 → gea_program-0.56.0}/gea/permits.py +0 -0
  262. {gea_program-0.54.0 → gea_program-0.56.0}/gea/piwebapi.py +0 -0
  263. {gea_program-0.54.0 → gea_program-0.56.0}/gea/pore_pressure.py +0 -0
  264. {gea_program-0.54.0 → gea_program-0.56.0}/gea/ports.py +0 -0
  265. {gea_program-0.54.0 → gea_program-0.56.0}/gea/ppdm.py +0 -0
  266. {gea_program-0.54.0 → gea_program-0.56.0}/gea/profile_catalog.py +0 -0
  267. {gea_program-0.54.0 → gea_program-0.56.0}/gea/project.py +0 -0
  268. {gea_program-0.54.0 → gea_program-0.56.0}/gea/qt6_downhole_app.py +0 -0
  269. {gea_program-0.54.0 → gea_program-0.56.0}/gea/quakeml.py +0 -0
  270. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reconciler.py +0 -0
  271. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  272. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  273. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/WMM2025.COF +0 -0
  274. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
  275. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/eia_prices.provenance.json +0 -0
  276. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
  277. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/iscwsa_rev4_example.json +0 -0
  278. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/iscwsa_rev5_example.json +0 -0
  279. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
  280. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
  281. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  282. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  283. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  284. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  285. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/mahoning_example.json +0 -0
  286. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/mud_motor_specs.json +0 -0
  287. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/owsg_tool_models.json +0 -0
  288. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/penetrator_ratings.json +0 -0
  289. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/seismicity_protocols.json +0 -0
  290. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/tool_sources.json +0 -0
  291. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/us_outline.json +0 -0
  292. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/us_outline.provenance.json +0 -0
  293. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_3d.provenance.json +0 -0
  294. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
  295. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
  296. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
  297. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_surfaces.json.gz +0 -0
  298. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
  299. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
  300. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
  301. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
  302. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
  303. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
  304. {gea_program-0.54.0 → gea_program-0.56.0}/gea/reference/volve_well_picks.csv.gz +0 -0
  305. {gea_program-0.54.0 → gea_program-0.56.0}/gea/report_history.py +0 -0
  306. {gea_program-0.54.0 → gea_program-0.56.0}/gea/rig_state.py +0 -0
  307. {gea_program-0.54.0 → gea_program-0.56.0}/gea/rock_inventory.py +0 -0
  308. {gea_program-0.54.0 → gea_program-0.56.0}/gea/sample_record.py +0 -0
  309. {gea_program-0.54.0 → gea_program-0.56.0}/gea/sample_well_profile.csv +0 -0
  310. {gea_program-0.54.0 → gea_program-0.56.0}/gea/sbom.py +0 -0
  311. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seedlink.py +0 -0
  312. {gea_program-0.54.0 → gea_program-0.56.0}/gea/segy.py +0 -0
  313. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic.py +0 -0
  314. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_array.py +0 -0
  315. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_assoc.py +0 -0
  316. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_detect.py +0 -0
  317. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_film.py +0 -0
  318. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_harmonic.py +0 -0
  319. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_qc.py +0 -0
  320. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_response.py +0 -0
  321. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_signature.py +0 -0
  322. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_track.py +0 -0
  323. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_uncertainty.py +0 -0
  324. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_unlisted.py +0 -0
  325. {gea_program-0.54.0 → gea_program-0.56.0}/gea/seismic_watch.py +0 -0
  326. {gea_program-0.54.0 → gea_program-0.56.0}/gea/sensor_swap.py +0 -0
  327. {gea_program-0.54.0 → gea_program-0.56.0}/gea/series_cache.py +0 -0
  328. {gea_program-0.54.0 → gea_program-0.56.0}/gea/service_life.py +0 -0
  329. {gea_program-0.54.0 → gea_program-0.56.0}/gea/setup_checklist.py +0 -0
  330. {gea_program-0.54.0 → gea_program-0.56.0}/gea/shapefile.py +0 -0
  331. {gea_program-0.54.0 → gea_program-0.56.0}/gea/shell.py +0 -0
  332. {gea_program-0.54.0 → gea_program-0.56.0}/gea/shut_in.py +0 -0
  333. {gea_program-0.54.0 → gea_program-0.56.0}/gea/simulation.py +0 -0
  334. {gea_program-0.54.0 → gea_program-0.56.0}/gea/site_map.py +0 -0
  335. {gea_program-0.54.0 → gea_program-0.56.0}/gea/sla_report.py +0 -0
  336. {gea_program-0.54.0 → gea_program-0.56.0}/gea/slip.py +0 -0
  337. {gea_program-0.54.0 → gea_program-0.56.0}/gea/soak.py +0 -0
  338. {gea_program-0.54.0 → gea_program-0.56.0}/gea/sra.py +0 -0
  339. {gea_program-0.54.0 → gea_program-0.56.0}/gea/store_forward.py +0 -0
  340. {gea_program-0.54.0 → gea_program-0.56.0}/gea/strata_join.py +0 -0
  341. {gea_program-0.54.0 → gea_program-0.56.0}/gea/structure.py +0 -0
  342. {gea_program-0.54.0 → gea_program-0.56.0}/gea/supervisor.py +0 -0
  343. {gea_program-0.54.0 → gea_program-0.56.0}/gea/survey_cmd.py +0 -0
  344. {gea_program-0.54.0 → gea_program-0.56.0}/gea/survey_view.py +0 -0
  345. {gea_program-0.54.0 → gea_program-0.56.0}/gea/telemetry.py +0 -0
  346. {gea_program-0.54.0 → gea_program-0.56.0}/gea/tool_catalog.py +0 -0
  347. {gea_program-0.54.0 → gea_program-0.56.0}/gea/tool_library.py +0 -0
  348. {gea_program-0.54.0 → gea_program-0.56.0}/gea/tool_taxonomy.py +0 -0
  349. {gea_program-0.54.0 → gea_program-0.56.0}/gea/torque_drag.py +0 -0
  350. {gea_program-0.54.0 → gea_program-0.56.0}/gea/transient.py +0 -0
  351. {gea_program-0.54.0 → gea_program-0.56.0}/gea/vibration.py +0 -0
  352. {gea_program-0.54.0 → gea_program-0.56.0}/gea/well3d.py +0 -0
  353. {gea_program-0.54.0 → gea_program-0.56.0}/gea/well_assembler.py +0 -0
  354. {gea_program-0.54.0 → gea_program-0.56.0}/gea/well_report.py +0 -0
  355. {gea_program-0.54.0 → gea_program-0.56.0}/gea/well_test_validation.py +0 -0
  356. {gea_program-0.54.0 → gea_program-0.56.0}/gea/wellplan.py +0 -0
  357. {gea_program-0.54.0 → gea_program-0.56.0}/gea/wellpos.py +0 -0
  358. {gea_program-0.54.0 → gea_program-0.56.0}/gea/wits0.py +0 -0
  359. {gea_program-0.54.0 → gea_program-0.56.0}/gea/witsml.py +0 -0
  360. {gea_program-0.54.0 → gea_program-0.56.0}/gea/workspace.py +0 -0
  361. {gea_program-0.54.0 → gea_program-0.56.0}/gea/xlsx_read.py +0 -0
  362. {gea_program-0.54.0 → gea_program-0.56.0}/gea_program.egg-info/dependency_links.txt +0 -0
  363. {gea_program-0.54.0 → gea_program-0.56.0}/gea_program.egg-info/entry_points.txt +0 -0
  364. {gea_program-0.54.0 → gea_program-0.56.0}/gea_program.egg-info/requires.txt +0 -0
  365. {gea_program-0.54.0 → gea_program-0.56.0}/gea_program.egg-info/top_level.txt +0 -0
  366. {gea_program-0.54.0 → gea_program-0.56.0}/setup.cfg +0 -0
  367. {gea_program-0.54.0 → gea_program-0.56.0}/tests/test_acceptance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gea-program
3
- Version: 0.54.0
3
+ Version: 0.56.0
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
@@ -243,7 +243,7 @@ disappearing. Every action is written to `records/audit.jsonl` with the
243
243
  actor's name and the SHA-256 of the inputs it used. The service is written on
244
244
  the standard library only (no new dependency, the standalone check still
245
245
  passes), listens on the loopback interface by default (`--host 0.0.0.0` for a
246
- site network, behind the site's TLS proxy), keeps sessions in HttpOnly
246
+ site network, over HTTPS - its own, below, or the site's TLS proxy), keeps sessions in HttpOnly
247
247
  SameSite cookies, and requires the page's own header on every action so a
248
248
  foreign form cannot act. Accounts live in `users.json` as salted PBKDF2-SHA256
249
249
  hashes; `gea users --workspace C:\site --action add --name ... --role admin`
@@ -1249,11 +1249,54 @@ is recomputed in the index. On the Reports page: the packets on record,
1249
1249
  Assemble as a job, and Schedule monthly (day and hour, the previous month).
1250
1250
  `gea help month-end`.
1251
1251
 
1252
+ ### HTTPS
1253
+
1254
+ The service speaks TLS itself when the workspace names a certificate: the
1255
+ site's own (from the company's certificate authority, which managed
1256
+ computers already trust; read where the site keeps it, at every start) or a
1257
+ self-signed one it makes with the standard library alone (an RSA key and an
1258
+ X.509 v3 server certificate for every name and address it is reached by).
1259
+ TLS 1.2 is the floor; the cookie is marked Secure; every answer carries
1260
+ Strict-Transport-Security; a plain `http://` request on the same port is
1261
+ sent to HTTPS; a certificate in its last 30 days raises the `tls.expiring`
1262
+ alert; a workspace whose certificate files are broken does not start rather
1263
+ than fall back to plain HTTP.
1264
+
1265
+ ```
1266
+ gea tls --workspace C:\site --site-cert C:\certs\gea-pad3.crt --site-key C:\certs\gea-pad3.key
1267
+ gea tls --workspace C:\site --self-signed --name gea-pad3 --name 10.20.0.15 --export-cert C:\certs\gea-site.crt
1268
+ gea serve --workspace C:\site --host 0.0.0.0 # https://gea-pad3:8765/
1269
+ ```
1270
+
1271
+ Or Administration -> **HTTPS** in the page (download the certificate, not
1272
+ the key, for the site's computers to trust; compare the SHA-256 shown).
1273
+ `gea help https`.
1274
+
1275
+ ### Company sign-in
1276
+
1277
+ People sign in with the account the company already manages - Microsoft
1278
+ Entra ID, Okta, Google Workspace, Ping, Keycloak, AD FS - by OpenID Connect
1279
+ (the authorization code flow with PKCE), so the company's multi-factor,
1280
+ conditional access and leavers apply. The ID token is checked with the
1281
+ standard library alone (its RS256 signature against the provider's
1282
+ published keys, the issuer, the audience, the times, the nonce); the role in
1283
+ GEA is the highest any of the person's app roles or groups maps to. Local
1284
+ accounts stay, for the first administrator and for when the provider cannot
1285
+ be reached. HTTPS comes first (above).
1286
+
1287
+ ```
1288
+ gea oidc --workspace C:\site --issuer https://login.microsoftonline.com/3f8b2c1d-6a4e-4d9b-8c2f-1e7a5b9d0c64/v2.0 --client-id a41c7e92-0d3b-4f6a-9e85-2b6d1c4f7a30 --redirect-uri https://gea-pad3.example.local:8765/api/oidc/callback --secret-from-env GEA_OIDC_SECRET --map GEA.Operator=operator --map GEA.Admin=admin --test
1289
+ ```
1290
+
1291
+ Or Administration -> **Company sign-in**. `gea help company-sign-in` has the
1292
+ Entra ID app registration step by step.
1293
+
1252
1294
  ### Before a site goes live
1253
1295
 
1254
- `deploy/README.md` is the checklist: keep the service on the loopback
1255
- address and put a TLS proxy in front (`deploy/Caddyfile`,
1256
- `deploy/nginx-gea.conf`), start with `--behind-proxy`. The service itself
1296
+ `deploy/README.md` is the checklist: HTTPS from the service itself (above),
1297
+ or keep the service on the loopback address and put the site's TLS proxy in
1298
+ front (`deploy/Caddyfile`, `deploy/nginx-gea.conf`), start with
1299
+ `--behind-proxy`. The service itself
1257
1300
  rate-limits sign-ins (five failures lock the name and the address for 15
1258
1301
  minutes, audited), lists and revokes live sessions, sends the security
1259
1302
  headers on every response, and `gea housekeeping --workspace C:\site --apply`
@@ -204,7 +204,7 @@ disappearing. Every action is written to `records/audit.jsonl` with the
204
204
  actor's name and the SHA-256 of the inputs it used. The service is written on
205
205
  the standard library only (no new dependency, the standalone check still
206
206
  passes), listens on the loopback interface by default (`--host 0.0.0.0` for a
207
- site network, behind the site's TLS proxy), keeps sessions in HttpOnly
207
+ site network, over HTTPS - its own, below, or the site's TLS proxy), keeps sessions in HttpOnly
208
208
  SameSite cookies, and requires the page's own header on every action so a
209
209
  foreign form cannot act. Accounts live in `users.json` as salted PBKDF2-SHA256
210
210
  hashes; `gea users --workspace C:\site --action add --name ... --role admin`
@@ -1210,11 +1210,54 @@ is recomputed in the index. On the Reports page: the packets on record,
1210
1210
  Assemble as a job, and Schedule monthly (day and hour, the previous month).
1211
1211
  `gea help month-end`.
1212
1212
 
1213
+ ### HTTPS
1214
+
1215
+ The service speaks TLS itself when the workspace names a certificate: the
1216
+ site's own (from the company's certificate authority, which managed
1217
+ computers already trust; read where the site keeps it, at every start) or a
1218
+ self-signed one it makes with the standard library alone (an RSA key and an
1219
+ X.509 v3 server certificate for every name and address it is reached by).
1220
+ TLS 1.2 is the floor; the cookie is marked Secure; every answer carries
1221
+ Strict-Transport-Security; a plain `http://` request on the same port is
1222
+ sent to HTTPS; a certificate in its last 30 days raises the `tls.expiring`
1223
+ alert; a workspace whose certificate files are broken does not start rather
1224
+ than fall back to plain HTTP.
1225
+
1226
+ ```
1227
+ gea tls --workspace C:\site --site-cert C:\certs\gea-pad3.crt --site-key C:\certs\gea-pad3.key
1228
+ gea tls --workspace C:\site --self-signed --name gea-pad3 --name 10.20.0.15 --export-cert C:\certs\gea-site.crt
1229
+ gea serve --workspace C:\site --host 0.0.0.0 # https://gea-pad3:8765/
1230
+ ```
1231
+
1232
+ Or Administration -> **HTTPS** in the page (download the certificate, not
1233
+ the key, for the site's computers to trust; compare the SHA-256 shown).
1234
+ `gea help https`.
1235
+
1236
+ ### Company sign-in
1237
+
1238
+ People sign in with the account the company already manages - Microsoft
1239
+ Entra ID, Okta, Google Workspace, Ping, Keycloak, AD FS - by OpenID Connect
1240
+ (the authorization code flow with PKCE), so the company's multi-factor,
1241
+ conditional access and leavers apply. The ID token is checked with the
1242
+ standard library alone (its RS256 signature against the provider's
1243
+ published keys, the issuer, the audience, the times, the nonce); the role in
1244
+ GEA is the highest any of the person's app roles or groups maps to. Local
1245
+ accounts stay, for the first administrator and for when the provider cannot
1246
+ be reached. HTTPS comes first (above).
1247
+
1248
+ ```
1249
+ gea oidc --workspace C:\site --issuer https://login.microsoftonline.com/3f8b2c1d-6a4e-4d9b-8c2f-1e7a5b9d0c64/v2.0 --client-id a41c7e92-0d3b-4f6a-9e85-2b6d1c4f7a30 --redirect-uri https://gea-pad3.example.local:8765/api/oidc/callback --secret-from-env GEA_OIDC_SECRET --map GEA.Operator=operator --map GEA.Admin=admin --test
1250
+ ```
1251
+
1252
+ Or Administration -> **Company sign-in**. `gea help company-sign-in` has the
1253
+ Entra ID app registration step by step.
1254
+
1213
1255
  ### Before a site goes live
1214
1256
 
1215
- `deploy/README.md` is the checklist: keep the service on the loopback
1216
- address and put a TLS proxy in front (`deploy/Caddyfile`,
1217
- `deploy/nginx-gea.conf`), start with `--behind-proxy`. The service itself
1257
+ `deploy/README.md` is the checklist: HTTPS from the service itself (above),
1258
+ or keep the service on the loopback address and put the site's TLS proxy in
1259
+ front (`deploy/Caddyfile`, `deploy/nginx-gea.conf`), start with
1260
+ `--behind-proxy`. The service itself
1218
1261
  rate-limits sign-ins (five failures lock the name and the address for 15
1219
1262
  minutes, audited), lists and revokes live sessions, sends the security
1220
1263
  headers on every response, and `gea housekeeping --workspace C:\site --apply`
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.54.0"
126
+ __version__ = "0.56.0"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -756,13 +756,44 @@ def main(argv=None) -> int:
756
756
 
757
757
  p_sv = sub.add_parser("serve", help="serve the dashboard over a workspace: the page, the reports and the JSON API (standard library HTTP)")
758
758
  p_sv.add_argument("--workspace", type=str, required=True, help="the workspace folder (gea workspace --action init)")
759
- p_sv.add_argument("--host", type=str, default="127.0.0.1", help="bind address; 0.0.0.0 exposes it on the site network (put TLS in front)")
759
+ p_sv.add_argument("--host", type=str, default="127.0.0.1", help="bind address; 0.0.0.0 exposes it on the site network (turn HTTPS on first: gea tls)")
760
760
  p_sv.add_argument("--port", type=int, default=8765)
761
761
  p_sv.add_argument("--workers", type=int, default=1, help="jobs run at once")
762
762
  p_sv.add_argument("--no-scheduler", action="store_true", help="do not run scheduled jobs from this process")
763
763
  p_sv.add_argument("--behind-proxy", action="store_true", help="a reverse proxy terminates TLS in front: trust X-Forwarded-For/-Proto, mark the cookie Secure (deploy/ has nginx and Caddy examples)")
764
764
  p_sv.add_argument("--no-browser", action="store_true", help="do not open the control panel in a browser once the service is listening (a scheduled start, a restart, a server with no desktop)")
765
765
 
766
+ p_tl = sub.add_parser("tls", help="HTTPS for the dashboard: the site's own certificate, a self-signed one made here, or off; with no option, how it stands")
767
+ p_tl.add_argument("--workspace", type=str, required=True)
768
+ p_tl.add_argument("--site-cert", type=str, default=None, help="the site's certificate (PEM, the server's first, then any chain) - read from where it is at every start")
769
+ p_tl.add_argument("--site-key", type=str, default=None, help="its private key (PEM, without a passphrase)")
770
+ p_tl.add_argument("--self-signed", action="store_true", help="make a self-signed certificate and key in the workspace's keys\\tls folder")
771
+ p_tl.add_argument("--name", action="append", default=[], help="--self-signed: a host name or address the dashboard is reached by (repeat; default: this machine's names, localhost, 127.0.0.1)")
772
+ p_tl.add_argument("--days", type=int, default=825, help="--self-signed: days valid (at most 825)")
773
+ p_tl.add_argument("--bits", type=int, default=2048, choices=[2048, 3072])
774
+ p_tl.add_argument("--off", action="store_true", help="plain HTTP from the next start (the files are left where they are)")
775
+ p_tl.add_argument("--export-cert", type=str, default=None, help="write the certificate (public, never the key) to this file, for the site's computers to trust")
776
+ p_tl.add_argument("--actor", type=str, default="cli")
777
+ p_tl.add_argument("--json", action="store_true")
778
+
779
+ p_oc = sub.add_parser("oidc", help="company sign-in (OpenID Connect: Entra ID, Okta, Google, Ping, Keycloak, AD FS): set it, test the provider, remove it; with no option, how it stands")
780
+ p_oc.add_argument("--workspace", type=str, required=True)
781
+ p_oc.add_argument("--issuer", type=str, default=None, help="Entra ID: https://login.microsoftonline.com/3f8b2c1d-6a4e-4d9b-8c2f-1e7a5b9d0c64/v2.0")
782
+ p_oc.add_argument("--client-id", type=str, default=None)
783
+ p_oc.add_argument("--redirect-uri", type=str, default=None, help="https://gea-pad3.example.local:8765/api/oidc/callback, registered with the provider exactly")
784
+ p_oc.add_argument("--secret-from-env", type=str, default=None, help="read the client secret from this environment variable now and keep it in keys\\oidc_client_secret.txt")
785
+ p_oc.add_argument("--secret-env", type=str, default=None, help="or: the service reads the client secret from this environment variable at each sign-in (nothing kept)")
786
+ p_oc.add_argument("--role-claim", type=str, default=None, help="roles (Entra ID app roles, the default) or groups, or any claim")
787
+ p_oc.add_argument("--map", action="append", default=[], help="VALUE=ROLE, e.g. GEA.Admin=admin (repeat)")
788
+ p_oc.add_argument("--default-role", type=str, default=None, help="the role of a person with no mapped value; 'none' (the default) means no sign-in")
789
+ p_oc.add_argument("--name-claim", type=str, default=None, help="the claim that names the person (preferred_username by default)")
790
+ p_oc.add_argument("--label", type=str, default=None, help="the sign-in button's words")
791
+ p_oc.add_argument("--pause", action="store_true", help="keep the settings, stop company sign-in")
792
+ p_oc.add_argument("--test", action="store_true", help="read the provider's discovery document and keys now")
793
+ p_oc.add_argument("--off", action="store_true", help="remove company sign-in (local accounts are unchanged)")
794
+ p_oc.add_argument("--actor", type=str, default="cli")
795
+ p_oc.add_argument("--json", action="store_true")
796
+
766
797
  p_hk = sub.add_parser("housekeeping", help="rotate the append-only logs, prune finished job folders and old live recordings (dry run unless --apply)")
767
798
  p_hk.add_argument("--workspace", type=str, required=True)
768
799
  p_hk.add_argument("--apply", action="store_true")
@@ -2603,6 +2634,88 @@ def main(argv=None) -> int:
2603
2634
  raise SystemExit(f"pore-pressure: {e.args[0] if e.args else e}")
2604
2635
  print(_json.dumps(r, default=str) if a.json else _PPF.text(r))
2605
2636
  return 0
2637
+ elif a.cmd == "oidc":
2638
+ import json as _json
2639
+ from . import oidc as _OI
2640
+ from .workspace import Workspace, WorkspaceError
2641
+ try:
2642
+ ws = Workspace(a.workspace)
2643
+ changing = any(x is not None for x in (a.issuer, a.client_id, a.redirect_uri, a.secret_from_env, a.secret_env, a.role_claim,
2644
+ a.default_role, a.name_claim, a.label)) or a.map or a.pause
2645
+ if a.off:
2646
+ r = _OI.turn_off(ws, a.actor)
2647
+ elif changing:
2648
+ cur = _OI.settings(ws) or {}
2649
+ s = {k: cur.get(k, v) for k, v in _OI.DEFAULTS.items()}
2650
+ for k, v in (("issuer", a.issuer), ("client_id", a.client_id), ("redirect_uri", a.redirect_uri), ("role_claim", a.role_claim),
2651
+ ("name_claim", a.name_claim), ("label", a.label), ("client_secret_env", a.secret_env)):
2652
+ if v is not None:
2653
+ s[k] = v
2654
+ if a.default_role is not None:
2655
+ s["default_role"] = None if a.default_role.lower() in ("", "none") else a.default_role
2656
+ if a.map:
2657
+ m = {}
2658
+ for x in a.map:
2659
+ v_, _, r_ = x.rpartition("=")
2660
+ if not v_:
2661
+ raise ValueError(f"--map takes VALUE=ROLE, not {x!r}")
2662
+ m[v_.strip()] = r_.strip()
2663
+ s["role_map"] = m
2664
+ if a.secret_from_env:
2665
+ s["client_secret_env"] = ""
2666
+ s["enabled"] = not a.pause
2667
+ sec = None
2668
+ if a.secret_from_env:
2669
+ sec = os.environ.get(a.secret_from_env, "")
2670
+ if not sec:
2671
+ raise ValueError(f"the environment variable {a.secret_from_env} is empty")
2672
+ r = _OI.configure(ws, a.actor, s, sec)
2673
+ else:
2674
+ r = _OI.status(ws)
2675
+ if a.test:
2676
+ r = {**r, "test": _OI.test(ws)}
2677
+ except (KeyError, ValueError, OSError, WorkspaceError) as e:
2678
+ raise SystemExit(f"oidc: {e.args[0] if e.args else e}")
2679
+ if a.json:
2680
+ print(_json.dumps(r, default=str))
2681
+ else:
2682
+ print(_OI.text(r))
2683
+ return 0
2684
+ elif a.cmd == "tls":
2685
+ import json as _json
2686
+ from . import tls as _TLS
2687
+ from .workspace import Workspace, WorkspaceError
2688
+ try:
2689
+ ws = Workspace(a.workspace)
2690
+ if sum(bool(x) for x in (a.self_signed, a.site_cert or a.site_key, a.off)) > 1:
2691
+ raise ValueError("one of --self-signed, --site-cert/--site-key or --off")
2692
+ if a.site_cert or a.site_key:
2693
+ if not (a.site_cert and a.site_key):
2694
+ raise ValueError("--site-cert and --site-key go together")
2695
+ r = _TLS.use_site_certificate(ws, a.actor, a.site_cert, a.site_key)
2696
+ elif a.self_signed:
2697
+ r = _TLS.make_self_signed(ws, a.actor, a.name or None, a.days, a.bits)
2698
+ elif a.off:
2699
+ r = _TLS.turn_off(ws, a.actor)
2700
+ else:
2701
+ r = _TLS.status(ws)
2702
+ if a.export_cert:
2703
+ pem = _TLS.certificate_pem(ws)
2704
+ if not pem:
2705
+ raise ValueError("HTTPS is off: there is no certificate to export")
2706
+ with open(a.export_cert, "wb") as f_:
2707
+ f_.write(pem)
2708
+ except (KeyError, ValueError, OSError, WorkspaceError) as e:
2709
+ raise SystemExit(f"tls: {e.args[0] if e.args else e}")
2710
+ if a.json:
2711
+ print(_json.dumps(r, default=str))
2712
+ else:
2713
+ print(_TLS.text(r))
2714
+ if a.self_signed or a.site_cert or a.off:
2715
+ print(" takes effect at the next start of the control panel (gea serve, or Restart on the Administration page)")
2716
+ if a.export_cert:
2717
+ print(f" certificate written to {a.export_cert} - hand this out, never the key")
2718
+ return 0
2606
2719
  elif a.cmd == "frac-hits":
2607
2720
  import json as _json
2608
2721
  from . import frac_hits as _FH
@@ -2946,18 +3059,29 @@ def main(argv=None) -> int:
2946
3059
  print(f"serve: BLOCK {mism}")
2947
3060
  if pre or mism:
2948
3061
  raise SystemExit("serve: not starting - fix the above (gea doctor --workspace ... shows the full picture)")
3062
+ from .tls import TlsError
2949
3063
  try:
2950
3064
  svc = Service(a.workspace, host=a.host, port=a.port, workers=a.workers, scheduler=not a.no_scheduler, behind_proxy=a.behind_proxy)
2951
3065
  except WorkspaceError as e:
2952
3066
  raise SystemExit(f"serve: {e}")
3067
+ except TlsError as e:
3068
+ raise SystemExit(f"serve: HTTPS is on for this workspace but {e}. Put the files right, or: gea tls --workspace \"{a.workspace}\" --off")
2953
3069
  n_users = svc.app.users.count()
2954
3070
  print(f"gea {__version__}: serving workspace '{svc.ws.manifest['name']}' at {svc.url}")
2955
3071
  print(f" code: {os.path.dirname(os.path.abspath(__file__))} (an installed copy serves the files it was installed from; pip install -e <clone> follows the clone)")
2956
3072
  print(f" patches: {len(svc.app.patches.store.list())} defined, {len([s for s in svc.app.patches.states() if s['status'] != 'STOPPED'])} running")
2957
3073
  if n_users == 0:
2958
3074
  print(" no accounts yet: the page will ask for the first administrator's name and password (one time), or run: gea users --workspace ... --action add --role admin --name ...")
2959
- if a.host not in ("127.0.0.1", "localhost", "::1") and not a.behind_proxy:
2960
- print(" NOTE: bound to a network address without --behind-proxy: traffic is plain HTTP. Put TLS in front (deploy/README.md) for anything beyond a trusted LAN.")
3075
+ if svc.tls_status:
3076
+ ts_ = svc.tls_status
3077
+ f_ = ts_.get("facts") or {}
3078
+ print(f" HTTPS ({ts_['state']}): {ts_['detail']}")
3079
+ print(f" names {', '.join(f_.get('names') or [])}; SHA-256 {f_.get('sha256_fingerprint')}")
3080
+ if f_.get("self_signed"):
3081
+ print(f" the certificate to hand out (never the key): {ts_['cert']} - or download it from the Administration page")
3082
+ elif a.host not in ("127.0.0.1", "localhost", "::1") and not a.behind_proxy:
3083
+ print(" NOTE: bound to a network address in plain HTTP. Turn HTTPS on (gea tls --workspace ... --site-cert/--site-key, or --self-signed),")
3084
+ print(" or put the site's TLS proxy in front (--behind-proxy; deploy/README.md), for anything beyond a trusted LAN.")
2961
3085
  print(" Ctrl+C stops it; every action is in records/audit.jsonl, every start and stop in records/runlog.jsonl")
2962
3086
  print(" the control panel's Stop and Restart end this run with a stated code: 0 stop, 86 start me again -")
2963
3087
  print(" the launcher reads it, and on anything but 86 it hands the window to a PowerShell prompt, never a Python one")