jerryproxy 0.1.0__tar.gz → 0.2.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 (206) hide show
  1. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/MANIFEST.in +0 -1
  2. {jerryproxy-0.1.0/jerryproxy.egg-info → jerryproxy-0.2.0}/PKG-INFO +68 -10
  3. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/README.md +67 -9
  4. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/errors.rst +7 -0
  5. jerryproxy-0.2.0/docs/source/api_doc/runtime/_logs.rst +14 -0
  6. jerryproxy-0.2.0/docs/source/api_doc/runtime/_probe.rst +15 -0
  7. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/runtime/health.rst +2 -2
  8. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/runtime/index.rst +1 -0
  9. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/runtime/interfaces.rst +2 -2
  10. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/runtime/mihomo.rst +1 -1
  11. jerryproxy-0.2.0/docs/source/api_doc/runtime/recovery.rst +40 -0
  12. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/index.rst +2 -1
  13. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/installation.rst +1 -1
  14. jerryproxy-0.2.0/docs/source/runtime_recovery.rst +220 -0
  15. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/anchored.py +4 -1
  16. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/server.py +195 -79
  17. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/config/meta.py +1 -1
  18. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/data/mihomo.json +197 -1
  19. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/data/sing-box.json +1201 -1
  20. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/data/v2ray.json +263 -1
  21. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/errors.py +14 -0
  22. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/lock.py +6 -0
  23. jerryproxy-0.2.0/jerryproxy/runtime/_logs.py +27 -0
  24. jerryproxy-0.2.0/jerryproxy/runtime/_probe.py +153 -0
  25. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/runtime/health.py +123 -63
  26. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/runtime/interfaces.py +12 -0
  27. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/runtime/mihomo.py +84 -19
  28. jerryproxy-0.2.0/jerryproxy/runtime/recovery.py +151 -0
  29. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/runtime/session.py +287 -194
  30. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/runner.py +2 -0
  31. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/runtime.py +46 -5
  32. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/manager.py +91 -26
  33. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/transport.py +44 -7
  34. {jerryproxy-0.1.0 → jerryproxy-0.2.0/jerryproxy.egg-info}/PKG-INFO +68 -10
  35. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy.egg-info/SOURCES.txt +7 -1
  36. jerryproxy-0.1.0/RELEASE_NOTES.md +0 -111
  37. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/LICENSE +0 -0
  38. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/THIRD_PARTY_LICENSES.md +0 -0
  39. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/auto_rst.py +0 -0
  40. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/auto_rst_top_index.py +0 -0
  41. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/Makefile +0 -0
  42. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/activation.rst +0 -0
  43. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/anchored.rst +0 -0
  44. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/archive.rst +0 -0
  45. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/archive_preflight.rst +0 -0
  46. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/catalog.rst +0 -0
  47. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/download.rst +0 -0
  48. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/durable.rst +0 -0
  49. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/identity.rst +0 -0
  50. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/index.rst +0 -0
  51. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/installation.rst +0 -0
  52. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/manager.rst +0 -0
  53. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/model.rst +0 -0
  54. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/platform.rst +0 -0
  55. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/recovery.rst +0 -0
  56. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/registry.rst +0 -0
  57. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/relay.rst +0 -0
  58. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/removal.rst +0 -0
  59. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/backend/state.rst +0 -0
  60. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/_common.rst +0 -0
  61. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/_completion.rst +0 -0
  62. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/clean.rst +0 -0
  63. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/current.rst +0 -0
  64. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/index.rst +0 -0
  65. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/install.rst +0 -0
  66. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/list.rst +0 -0
  67. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/uninstall.rst +0 -0
  68. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/use.rst +0 -0
  69. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/verify.rst +0 -0
  70. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/backend/which.rst +0 -0
  71. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/doctor.rst +0 -0
  72. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/home.rst +0 -0
  73. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/index.rst +0 -0
  74. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/node/index.rst +0 -0
  75. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/node/list.rst +0 -0
  76. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/self_check.rst +0 -0
  77. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/server.rst +0 -0
  78. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/_common.rst +0 -0
  79. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/add.rst +0 -0
  80. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/index.rst +0 -0
  81. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/list.rst +0 -0
  82. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/refresh.rst +0 -0
  83. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/remove.rst +0 -0
  84. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/replace.rst +0 -0
  85. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/show.rst +0 -0
  86. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/cli/subscription/validate.rst +0 -0
  87. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/config/index.rst +0 -0
  88. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/config/meta.rst +0 -0
  89. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/data/index.rst +0 -0
  90. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/home.rst +0 -0
  91. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/index.rst +0 -0
  92. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/lock.rst +0 -0
  93. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/runtime/guardian.rst +0 -0
  94. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/runtime/session.rst +0 -0
  95. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/backend.rst +0 -0
  96. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/dependencies.rst +0 -0
  97. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/environment.rst +0 -0
  98. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/fixtures.rst +0 -0
  99. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/index.rst +0 -0
  100. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/processes.rst +0 -0
  101. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/recovery.rst +0 -0
  102. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/relay.rst +0 -0
  103. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/resources.rst +0 -0
  104. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/result.rst +0 -0
  105. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/runner.rst +0 -0
  106. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/runtime.rst +0 -0
  107. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/selfcheck/subscription.rst +0 -0
  108. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/audit.rst +0 -0
  109. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/index.rst +0 -0
  110. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/interfaces.rst +0 -0
  111. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/manager.rst +0 -0
  112. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/model.rst +0 -0
  113. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/redaction.rst +0 -0
  114. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/storage.rst +0 -0
  115. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/subscription/transport.rst +0 -0
  116. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/utils/fs.rst +0 -0
  117. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc/utils/index.rst +0 -0
  118. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/api_doc.rst +0 -0
  119. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/architecture.rst +0 -0
  120. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/backend_manager.rst +0 -0
  121. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/conf.py +0 -0
  122. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/roadmap.rst +0 -0
  123. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/docs/source/security.rst +0 -0
  124. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/__init__.py +0 -0
  125. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/__main__.py +0 -0
  126. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/__init__.py +0 -0
  127. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/activation.py +0 -0
  128. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/archive.py +0 -0
  129. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/archive_preflight.py +0 -0
  130. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/catalog.py +0 -0
  131. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/download.py +0 -0
  132. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/durable.py +0 -0
  133. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/identity.py +0 -0
  134. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/installation.py +0 -0
  135. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/manager.py +0 -0
  136. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/model.py +0 -0
  137. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/platform.py +0 -0
  138. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/recovery.py +0 -0
  139. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/registry.py +0 -0
  140. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/relay.py +0 -0
  141. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/removal.py +0 -0
  142. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/backend/state.py +0 -0
  143. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/__init__.py +0 -0
  144. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/_common.py +0 -0
  145. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/_completion.py +0 -0
  146. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/__init__.py +0 -0
  147. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/clean.py +0 -0
  148. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/current.py +0 -0
  149. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/install.py +0 -0
  150. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/list.py +0 -0
  151. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/uninstall.py +0 -0
  152. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/use.py +0 -0
  153. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/verify.py +0 -0
  154. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/backend/which.py +0 -0
  155. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/doctor.py +0 -0
  156. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/home.py +0 -0
  157. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/node/__init__.py +0 -0
  158. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/node/list.py +0 -0
  159. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/self_check.py +0 -0
  160. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/__init__.py +0 -0
  161. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/_common.py +0 -0
  162. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/add.py +0 -0
  163. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/list.py +0 -0
  164. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/refresh.py +0 -0
  165. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/remove.py +0 -0
  166. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/replace.py +0 -0
  167. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/show.py +0 -0
  168. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/cli/subscription/validate.py +0 -0
  169. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/config/__init__.py +0 -0
  170. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/data/__init__.py +0 -0
  171. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/data/xray.json +0 -0
  172. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/home.py +0 -0
  173. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/runtime/__init__.py +0 -0
  174. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/runtime/guardian.py +0 -0
  175. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/__init__.py +0 -0
  176. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/backend.py +0 -0
  177. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/dependencies.py +0 -0
  178. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/environment.py +0 -0
  179. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/fixtures.py +0 -0
  180. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/processes.py +0 -0
  181. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/recovery.py +0 -0
  182. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/relay.py +0 -0
  183. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/resources.py +0 -0
  184. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/result.py +0 -0
  185. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/selfcheck/subscription.py +0 -0
  186. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/__init__.py +0 -0
  187. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/audit.py +0 -0
  188. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/interfaces.py +0 -0
  189. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/model.py +0 -0
  190. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/redaction.py +0 -0
  191. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/subscription/storage.py +0 -0
  192. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/utils/__init__.py +0 -0
  193. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy/utils/fs.py +0 -0
  194. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy.egg-info/dependency_links.txt +0 -0
  195. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy.egg-info/entry_points.txt +0 -0
  196. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy.egg-info/requires.txt +0 -0
  197. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/jerryproxy.egg-info/top_level.txt +0 -0
  198. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/pyproject.toml +0 -0
  199. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/requirements-build.txt +0 -0
  200. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/requirements-dev.txt +0 -0
  201. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/requirements-doc.txt +0 -0
  202. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/requirements-test.txt +0 -0
  203. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/requirements.txt +0 -0
  204. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/setup.cfg +0 -0
  205. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/setup.py +0 -0
  206. {jerryproxy-0.1.0 → jerryproxy-0.2.0}/test/test_structure.py +0 -0
@@ -1,7 +1,6 @@
1
1
  include LICENSE
2
2
  include THIRD_PARTY_LICENSES.md
3
3
  include README.md
4
- include RELEASE_NOTES.md
5
4
  include auto_rst.py
6
5
  include auto_rst_top_index.py
7
6
  include requirements.txt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jerryproxy
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: An out-of-the-box multi-backend proxy CLI and backend manager.
5
5
  Home-page: https://github.com/narugo1992/jerryproxy
6
6
  Author: narugo1992
@@ -46,7 +46,7 @@ switching, and eventually orchestrating multiple external proxy backends. The
46
46
  PyPI distribution, Python import, GitHub repository, CLI command, and default
47
47
  home directory all use the same name: `jerryproxy`.
48
48
 
49
- > **0.1.0 alpha-quality release:** the first runtime slice is implemented: bounded
49
+ > **0.2.0 release preparation (alpha quality):** the current runtime slice implements bounded
50
50
  > `V2RAY_SUBSCRIPTION` ingestion for Base64/plain SS, VMess, VLESS, Trojan,
51
51
  > Hysteria2, TUIC, and AnyTLS URI
52
52
  > lines and Mihomo/Clash provider YAML, which keeps the supported nodes of a
@@ -58,7 +58,7 @@ home directory all use the same name: `jerryproxy`.
58
58
  > credentials and `--bind-all` explicitly selects `0.0.0.0`. Native profiles,
59
59
  > other core drivers, and the historical `v2raycli` compatibility layer remain
60
60
  > planned. This is the first public release; the `0.x` API and state formats are
61
- > not stable yet. See the [release notes](https://github.com/narugo1992/jerryproxy/blob/main/RELEASE_NOTES.md) for the complete
61
+ > not stable yet. See the [release notes](https://github.com/narugo1992/jerryproxy/releases/latest) for the complete
62
62
  > scope, verification evidence, and known limitations.
63
63
 
64
64
  ## Current status
@@ -130,7 +130,8 @@ Python.
130
130
 
131
131
  ## Installation
132
132
 
133
- The first public release is `0.1.0`. It is an alpha-quality `0.x` release, so
133
+ The source tree is prepared for `0.2.0`; publication is pending. The first
134
+ public release was `0.1.0`. This remains an alpha-quality `0.x` project, so
134
135
  the API and managed-state formats may change between releases. Install it from
135
136
  PyPI with:
136
137
 
@@ -379,7 +380,9 @@ backend registry, packaged catalog access and selection, `filelock`
379
380
  compatibility, and one lock-consistent installed/active backend inventory. It
380
381
  also exercises a complete synthetic backend lifecycle plus install, activation,
381
382
  and removal hard-exit recovery in isolated temporary JerryProxy homes without
382
- changing the configured home. It then streams one fixed 1 MiB Range from
383
+ changing the configured home. A separate health-worker check spawns the actual
384
+ network worker against a temporary loopback HTTP server, verifies the
385
+ response and confirms cleanup without external traffic. It then streams one fixed 1 MiB Range from
383
386
  a pinned public Xray release through each built-in relay. The probe separates
384
387
  response-header latency, first-chunk latency, and the speed of the remaining
385
388
  chunks, uses a five-second connect/read timeout, and has a parent-enforced
@@ -486,6 +489,14 @@ prefers GitHub API digests, and reads official checksum text only for legacy
486
489
  assets where the API has no digest. It never downloads backend archives to
487
490
  calculate catalog fingerprints. The updater is not included in the wheel.
488
491
 
492
+ Scheduled and manual runs first look for an open catalog review. New reviews
493
+ use the exact title `chore(catalog): refresh backend release catalogs` and the
494
+ body marker `<!-- jerryproxy:backend-catalog-refresh -->`; both must match.
495
+ Existing legacy bot reviews are also recognized by title, author, and branch.
496
+ When a review is open, the run comments on the newest matching PR and skips
497
+ refreshing or publishing a branch. After that review is merged or closed, a
498
+ later run may create a new review. Query failures stop the workflow.
499
+
489
500
  Relay-health monitoring is also repository infrastructure, not JerryProxy
490
501
  runtime behavior. Its 57-site configuration lives in a dedicated
491
502
  [Gist](https://gist.github.com/narugo1992/78fb0ee6135fcdf4f0e5c7ec38f2fd59).
@@ -540,10 +551,57 @@ SOCKS5 listener uses a `socks5h` URL. Backend stdout/stderr are merged into one
540
551
  bounded live stream, redacted, and labeled only with the backend name
541
552
  (`[mihomo]`), never separate stdout/stderr labels; `--backend-log-level`
542
553
  defaults to `INFO`. Two consecutive
543
- failed global health quorums trigger one same-node restart, deterministic
544
- alternate-node attempts, and one optional subscription refresh within the
545
- configured recovery deadline. Automatic recovery never rewrites the saved node
546
- preference.
554
+ failed global health quorums trigger persistent recovery within the selected
555
+ subscription. Health checks default to 30 seconds, with a confirmation check
556
+ 3 seconds after a failure. The backend stays running while nodes are retried
557
+ and hot-reloaded; each recovery round has its own budget and capped backoff.
558
+ Healthy sessions keep their node, listener and credentials, and automatic
559
+ recovery never rewrites the saved preference. Temporary subscription transport
560
+ failures retain verified cache, with separate refresh backoff and Retry-After
561
+ handling. Cache older than 12 hours requests refresh without disqualifying its
562
+ nodes. Control, TLS, authentication, integrity and unclassified failures remain
563
+ terminal. Lifecycle events report starting, degradation, retry attempts,
564
+ refresh outcomes, readiness and completed cleanup. JSONL sends events to stdout
565
+ and ordinary logs to stderr; event visibility is independent of log level.
566
+ Both log producers retain recent redacted diagnostics within a 4 MiB file.
567
+ SIGINT and SIGTERM unwind the foreground session and exit with status 130
568
+ and 143 after cleanup; repeated signals do not interrupt that cleanup. Default
569
+ health requests run in a disposable process that is stopped at the wall deadline,
570
+ so stalled network requests cannot occupy future probe batches. Unconfirmed
571
+ worker cleanup is terminal and retains the home lock; recovery never hides an
572
+ unsafe process state. Existing client connections are not guaranteed to survive
573
+ a node change.
574
+
575
+ Choose `--retry-policy none|fixed|random|adaptive|fallback` in a complete command
576
+ or select the same policy in the guided TTY flow. The default `fallback` uses
577
+ `current:1,adaptive:3,random:all`; `--retry-chain current:1,random:all` selects a
578
+ custom fallback chain. Stages must be unique, counts must be positive integers
579
+ (up to 10,000) or `all`, and `current` permits only `current:1`. Custom chains
580
+ require `fallback`. `none` stops on confirmed failure and disables refresh;
581
+ `fixed` never substitutes a different initial identity; `random` visits nodes
582
+ without replacement; `adaptive` uses aging session-local successes with
583
+ recovery-only exploration. Human and JSONL startup report the chosen policy.
584
+
585
+ Defaults target subscriptions with up to 20 nodes. Recovery first uses short
586
+ 3-second health probes, then normal budgets after the fast sweep is exhausted
587
+ so slow usable nodes remain eligible. After 6 seconds spent trying cached
588
+ nodes, the next between-attempt check gives subscription refresh its own
589
+ 10-second budget; a large old pool cannot consume that fetch budget. Refresh
590
+ starts at most once per 60 seconds by default, with additional transport
591
+ backoff and Retry-After handling. Changed content is tried without an extra
592
+ round backoff. An in-flight bounded attempt finishes before the refresh check;
593
+ these timings are not a guarantee that an available route exists.
594
+
595
+ Advanced overrides are `--fast-probe-timeout 3`, `--cache-retry-budget 6`,
596
+ `--refresh-timeout 10` and `--refresh-interval 60` (all seconds). Complete
597
+ commands and guided selection share these defaults and overrides. The guided
598
+ flow adds no timing questions; choosing the recommended policy is sufficient.
599
+
600
+ ```shell
601
+ jerryproxy server --subscription main --node NODE_ID --retry-policy fixed
602
+ jerryproxy server --subscription main --node NODE_ID --retry-policy fallback \
603
+ --retry-chain current:1,adaptive:3,random:all
604
+ ```
547
605
 
548
606
  Nodes are listed with the label their provider put in the URI fragment, so
549
607
  several endpoints of one protocol stay distinguishable. That fragment is
@@ -627,7 +685,7 @@ tampering and is never repaired automatically.
627
685
  - [x] Implement managed `V2RAY_SUBSCRIPTION` fetch, private state, and URI
628
686
  inventory for every encrypted protocol the qualified backend accepts.
629
687
  - [x] Implement the Mihomo foreground driver, loopback listener, merged named
630
- backend stream, and bounded health recovery.
688
+ backend stream, and persistent health recovery with bounded rounds.
631
689
  - [ ] Implement durable controller operations, measurements, and service
632
690
  integration.
633
691
  - [ ] Preserve documented `v2raycli` inputs through deprecated aliases.
@@ -5,7 +5,7 @@ switching, and eventually orchestrating multiple external proxy backends. The
5
5
  PyPI distribution, Python import, GitHub repository, CLI command, and default
6
6
  home directory all use the same name: `jerryproxy`.
7
7
 
8
- > **0.1.0 alpha-quality release:** the first runtime slice is implemented: bounded
8
+ > **0.2.0 release preparation (alpha quality):** the current runtime slice implements bounded
9
9
  > `V2RAY_SUBSCRIPTION` ingestion for Base64/plain SS, VMess, VLESS, Trojan,
10
10
  > Hysteria2, TUIC, and AnyTLS URI
11
11
  > lines and Mihomo/Clash provider YAML, which keeps the supported nodes of a
@@ -17,7 +17,7 @@ home directory all use the same name: `jerryproxy`.
17
17
  > credentials and `--bind-all` explicitly selects `0.0.0.0`. Native profiles,
18
18
  > other core drivers, and the historical `v2raycli` compatibility layer remain
19
19
  > planned. This is the first public release; the `0.x` API and state formats are
20
- > not stable yet. See the [release notes](https://github.com/narugo1992/jerryproxy/blob/main/RELEASE_NOTES.md) for the complete
20
+ > not stable yet. See the [release notes](https://github.com/narugo1992/jerryproxy/releases/latest) for the complete
21
21
  > scope, verification evidence, and known limitations.
22
22
 
23
23
  ## Current status
@@ -89,7 +89,8 @@ Python.
89
89
 
90
90
  ## Installation
91
91
 
92
- The first public release is `0.1.0`. It is an alpha-quality `0.x` release, so
92
+ The source tree is prepared for `0.2.0`; publication is pending. The first
93
+ public release was `0.1.0`. This remains an alpha-quality `0.x` project, so
93
94
  the API and managed-state formats may change between releases. Install it from
94
95
  PyPI with:
95
96
 
@@ -338,7 +339,9 @@ backend registry, packaged catalog access and selection, `filelock`
338
339
  compatibility, and one lock-consistent installed/active backend inventory. It
339
340
  also exercises a complete synthetic backend lifecycle plus install, activation,
340
341
  and removal hard-exit recovery in isolated temporary JerryProxy homes without
341
- changing the configured home. It then streams one fixed 1 MiB Range from
342
+ changing the configured home. A separate health-worker check spawns the actual
343
+ network worker against a temporary loopback HTTP server, verifies the
344
+ response and confirms cleanup without external traffic. It then streams one fixed 1 MiB Range from
342
345
  a pinned public Xray release through each built-in relay. The probe separates
343
346
  response-header latency, first-chunk latency, and the speed of the remaining
344
347
  chunks, uses a five-second connect/read timeout, and has a parent-enforced
@@ -445,6 +448,14 @@ prefers GitHub API digests, and reads official checksum text only for legacy
445
448
  assets where the API has no digest. It never downloads backend archives to
446
449
  calculate catalog fingerprints. The updater is not included in the wheel.
447
450
 
451
+ Scheduled and manual runs first look for an open catalog review. New reviews
452
+ use the exact title `chore(catalog): refresh backend release catalogs` and the
453
+ body marker `<!-- jerryproxy:backend-catalog-refresh -->`; both must match.
454
+ Existing legacy bot reviews are also recognized by title, author, and branch.
455
+ When a review is open, the run comments on the newest matching PR and skips
456
+ refreshing or publishing a branch. After that review is merged or closed, a
457
+ later run may create a new review. Query failures stop the workflow.
458
+
448
459
  Relay-health monitoring is also repository infrastructure, not JerryProxy
449
460
  runtime behavior. Its 57-site configuration lives in a dedicated
450
461
  [Gist](https://gist.github.com/narugo1992/78fb0ee6135fcdf4f0e5c7ec38f2fd59).
@@ -499,10 +510,57 @@ SOCKS5 listener uses a `socks5h` URL. Backend stdout/stderr are merged into one
499
510
  bounded live stream, redacted, and labeled only with the backend name
500
511
  (`[mihomo]`), never separate stdout/stderr labels; `--backend-log-level`
501
512
  defaults to `INFO`. Two consecutive
502
- failed global health quorums trigger one same-node restart, deterministic
503
- alternate-node attempts, and one optional subscription refresh within the
504
- configured recovery deadline. Automatic recovery never rewrites the saved node
505
- preference.
513
+ failed global health quorums trigger persistent recovery within the selected
514
+ subscription. Health checks default to 30 seconds, with a confirmation check
515
+ 3 seconds after a failure. The backend stays running while nodes are retried
516
+ and hot-reloaded; each recovery round has its own budget and capped backoff.
517
+ Healthy sessions keep their node, listener and credentials, and automatic
518
+ recovery never rewrites the saved preference. Temporary subscription transport
519
+ failures retain verified cache, with separate refresh backoff and Retry-After
520
+ handling. Cache older than 12 hours requests refresh without disqualifying its
521
+ nodes. Control, TLS, authentication, integrity and unclassified failures remain
522
+ terminal. Lifecycle events report starting, degradation, retry attempts,
523
+ refresh outcomes, readiness and completed cleanup. JSONL sends events to stdout
524
+ and ordinary logs to stderr; event visibility is independent of log level.
525
+ Both log producers retain recent redacted diagnostics within a 4 MiB file.
526
+ SIGINT and SIGTERM unwind the foreground session and exit with status 130
527
+ and 143 after cleanup; repeated signals do not interrupt that cleanup. Default
528
+ health requests run in a disposable process that is stopped at the wall deadline,
529
+ so stalled network requests cannot occupy future probe batches. Unconfirmed
530
+ worker cleanup is terminal and retains the home lock; recovery never hides an
531
+ unsafe process state. Existing client connections are not guaranteed to survive
532
+ a node change.
533
+
534
+ Choose `--retry-policy none|fixed|random|adaptive|fallback` in a complete command
535
+ or select the same policy in the guided TTY flow. The default `fallback` uses
536
+ `current:1,adaptive:3,random:all`; `--retry-chain current:1,random:all` selects a
537
+ custom fallback chain. Stages must be unique, counts must be positive integers
538
+ (up to 10,000) or `all`, and `current` permits only `current:1`. Custom chains
539
+ require `fallback`. `none` stops on confirmed failure and disables refresh;
540
+ `fixed` never substitutes a different initial identity; `random` visits nodes
541
+ without replacement; `adaptive` uses aging session-local successes with
542
+ recovery-only exploration. Human and JSONL startup report the chosen policy.
543
+
544
+ Defaults target subscriptions with up to 20 nodes. Recovery first uses short
545
+ 3-second health probes, then normal budgets after the fast sweep is exhausted
546
+ so slow usable nodes remain eligible. After 6 seconds spent trying cached
547
+ nodes, the next between-attempt check gives subscription refresh its own
548
+ 10-second budget; a large old pool cannot consume that fetch budget. Refresh
549
+ starts at most once per 60 seconds by default, with additional transport
550
+ backoff and Retry-After handling. Changed content is tried without an extra
551
+ round backoff. An in-flight bounded attempt finishes before the refresh check;
552
+ these timings are not a guarantee that an available route exists.
553
+
554
+ Advanced overrides are `--fast-probe-timeout 3`, `--cache-retry-budget 6`,
555
+ `--refresh-timeout 10` and `--refresh-interval 60` (all seconds). Complete
556
+ commands and guided selection share these defaults and overrides. The guided
557
+ flow adds no timing questions; choosing the recommended policy is sufficient.
558
+
559
+ ```shell
560
+ jerryproxy server --subscription main --node NODE_ID --retry-policy fixed
561
+ jerryproxy server --subscription main --node NODE_ID --retry-policy fallback \
562
+ --retry-chain current:1,adaptive:3,random:all
563
+ ```
506
564
 
507
565
  Nodes are listed with the label their provider put in the URI fragment, so
508
566
  several endpoints of one protocol stay distinguishable. That fragment is
@@ -586,7 +644,7 @@ tampering and is never repaired automatically.
586
644
  - [x] Implement managed `V2RAY_SUBSCRIPTION` fetch, private state, and URI
587
645
  inventory for every encrypted protocol the qualified backend accepts.
588
646
  - [x] Implement the Mihomo foreground driver, loopback listener, merged named
589
- backend stream, and bounded health recovery.
647
+ backend stream, and persistent health recovery with bounded rounds.
590
648
  - [ ] Implement durable controller operations, measurements, and service
591
649
  integration.
592
650
  - [ ] Preserve documented `v2raycli` inputs through deprecated aliases.
@@ -115,6 +115,13 @@ SubscriptionFetchError
115
115
  .. autoclass:: SubscriptionFetchError
116
116
 
117
117
 
118
+ SubscriptionTransportError
119
+ -----------------------------------------------------
120
+
121
+ .. autoclass:: SubscriptionTransportError
122
+ :members: __init__
123
+
124
+
118
125
  SubscriptionParseError
119
126
  -----------------------------------------------------
120
127
 
@@ -0,0 +1,14 @@
1
+ :orphan:
2
+
3
+ jerryproxy.runtime.\_logs
4
+ ========================================================
5
+
6
+ .. currentmodule:: jerryproxy.runtime._logs
7
+
8
+ .. automodule:: jerryproxy.runtime._logs
9
+
10
+
11
+ append\_recent
12
+ -----------------------------------------------------
13
+
14
+ .. autofunction:: append_recent
@@ -0,0 +1,15 @@
1
+ :orphan:
2
+
3
+ jerryproxy.runtime.\_probe
4
+ ========================================================
5
+
6
+ .. currentmodule:: jerryproxy.runtime._probe
7
+
8
+ .. automodule:: jerryproxy.runtime._probe
9
+
10
+
11
+ ProbeProcess
12
+ -----------------------------------------------------
13
+
14
+ .. autoclass:: ProbeProcess
15
+ :members: __init__,close,check
@@ -45,14 +45,14 @@ ConnectivityProbe
45
45
  -----------------------------------------------------
46
46
 
47
47
  .. autoclass:: ConnectivityProbe
48
- :members: __init__,check
48
+ :members: __init__,check,close
49
49
 
50
50
 
51
51
  RecoveryPolicy
52
52
  -----------------------------------------------------
53
53
 
54
54
  .. autoclass:: RecoveryPolicy
55
- :members: health_interval,recovery_deadline,startup_retry_delays,same_node_delay,alternate_delays,refresh_on_failure,refresh_stale_seconds,failure_cooldown,__post_init__
55
+ :members: retry_policy,retry_chain,confirmation_delay,refresh_interval,fast_probe_timeout,cache_retry_budget,refresh_timeout,health_interval,recovery_deadline,refresh_on_failure,refresh_stale_seconds,__post_init__
56
56
 
57
57
 
58
58
  RecoveryDeadline
@@ -13,6 +13,7 @@ jerryproxy.runtime
13
13
  health
14
14
  interfaces
15
15
  mihomo
16
+ recovery
16
17
  session
17
18
 
18
19
  \_\_all\_\_
@@ -17,11 +17,11 @@ LoadedNodes
17
17
  -----------------------------------------------------
18
18
 
19
19
  .. autoclass:: LoadedNodes
20
- :members: accepted,selected,bypassing
20
+ :members: accepted,selected,bypassing,identities
21
21
 
22
22
 
23
23
  RuntimeDriver
24
24
  -----------------------------------------------------
25
25
 
26
26
  .. autoclass:: RuntimeDriver
27
- :members: name,projection,loaded_nodes,create_process,wait_ready,stop
27
+ :members: name,projection,loaded_nodes,reload_provider,create_process,wait_ready,stop
@@ -52,7 +52,7 @@ MihomoDriver
52
52
  -----------------------------------------------------
53
53
 
54
54
  .. autoclass:: MihomoDriver
55
- :members: __init__,name,projection,loaded_nodes,create_process,wait_ready,stop
55
+ :members: __init__,name,projection,loaded_nodes,reload_provider,create_process,wait_ready,stop
56
56
 
57
57
 
58
58
  MihomoProcess
@@ -0,0 +1,40 @@
1
+ jerryproxy.runtime.recovery
2
+ ========================================================
3
+
4
+ .. currentmodule:: jerryproxy.runtime.recovery
5
+
6
+ .. automodule:: jerryproxy.runtime.recovery
7
+
8
+
9
+ DEFAULT\_RETRY\_CHAIN
10
+ -----------------------------------------------------
11
+
12
+ .. autodata:: DEFAULT_RETRY_CHAIN
13
+ :no-value:
14
+
15
+
16
+ RETRY\_POLICIES
17
+ -----------------------------------------------------
18
+
19
+ .. autodata:: RETRY_POLICIES
20
+ :no-value:
21
+
22
+
23
+ RetrySchedule
24
+ -----------------------------------------------------
25
+
26
+ .. autoclass:: RetrySchedule
27
+ :members: __init__,begin_sweep,update,record,wait_seconds,next
28
+
29
+
30
+ RetryBackoff
31
+ -----------------------------------------------------
32
+
33
+ .. autoclass:: RetryBackoff
34
+ :members: __init__,healthy,failed
35
+
36
+
37
+ parse\_retry\_chain
38
+ -----------------------------------------------------
39
+
40
+ .. autofunction:: parse_retry_chain
@@ -5,7 +5,7 @@ JerryProxy is a Python 3.7+ multi-backend proxy CLI and backend manager.
5
5
 
6
6
  .. warning::
7
7
 
8
- JerryProxy 0.1.0 is the first public, alpha-quality release. The current
8
+ JerryProxy 0.2.0 is prepared for release; publication is pending. The current
9
9
  runtime slice accepts bounded ``V2RAY_SUBSCRIPTION`` URI sources and
10
10
  Mihomo/Clash proxy-provider YAML for the encrypted protocols the qualified
11
11
  backend accepts, and runs Mihomo 1.19.29 in the foreground. Native profiles,
@@ -21,4 +21,5 @@ JerryProxy is a Python 3.7+ multi-backend proxy CLI and backend manager.
21
21
  architecture
22
22
  security
23
23
  roadmap
24
+ runtime_recovery
24
25
  api_doc
@@ -1,7 +1,7 @@
1
1
  Installation
2
2
  ============
3
3
 
4
- JerryProxy 0.1.0 is the first public, alpha-quality release. It supports Python
4
+ JerryProxy 0.2.0 is prepared for release; publication is pending. It supports Python
5
5
  3.7 and newer and is distributed as a pure-Python wheel. The ``0.x`` API and
6
6
  managed-state formats are not stable yet.
7
7
 
@@ -0,0 +1,220 @@
1
+ Persistent recovery implementation contract
2
+ ===========================================
3
+
4
+ This contract defines persistent recovery and its merge acceptance criteria.
5
+ It implements the maintainer's
6
+ Chinese design document, revision 8, dated 2026-09-21.
7
+
8
+ Inputs and boundaries
9
+ ---------------------
10
+
11
+ The caller explicitly selects one subscription and one initial node. Recovery
12
+ must never leave that subscription, change its saved preference, interpret
13
+ protocol credentials, or replace the existing runtime-driver boundary.
14
+ Healthy sessions keep their current node; exploration and exit-IP changes
15
+ are permitted only during recovery. There is no automatic failback.
16
+
17
+ Startup and periodic outages use the same recovery path. Transient outages
18
+ have no session lifetime limit. Each probe, reload, refresh, cleanup and retry
19
+ round remains bounded. A round deadline preserves pending candidates rather
20
+ than repeatedly starving the tail of a large subscription.
21
+
22
+ Fast recovery defaults
23
+ ----------------------
24
+
25
+ For subscriptions with up to 20 nodes, the first recovery sweep uses a
26
+ three-second health budget per candidate. After six seconds on cached
27
+ candidates, the next between-attempt check gives a source refresh an
28
+ independent ten-second budget. An in-flight bounded reload/probe completes
29
+ before this check; six seconds is a scheduling threshold, not a hard wall.
30
+ Refresh is checked between attempts and rounds, never only against the
31
+ remaining round budget. Its default minimum interval is 60 seconds, with
32
+ transport backoff and Retry-After still enforced. Changed source content is
33
+ eligible immediately without an extra round backoff. An exhausted fast sweep
34
+ falls back to normal probe budgets so slow usable nodes are not excluded.
35
+ Healthy sessions retain the existing check interval and never explore.
36
+
37
+ These defaults target fast restoration rather than an optimal-node search.
38
+ Verification compares 1, 5, 10 and 20-node replacement and partial-outage
39
+ scenarios, including slow usable nodes, unchanged/failed refresh, deadline
40
+ exhaustion and CLI/guided default and override parity. Simulated timing is
41
+ not a public-network latency guarantee. Safety and cleanup remain terminal
42
+ boundaries. Advanced timing options must not add guided questions.
43
+
44
+ ``--fast-probe-timeout`` (3), ``--cache-retry-budget`` (6),
45
+ ``--refresh-timeout`` (10) and ``--refresh-interval`` (60) are advanced
46
+ overrides in seconds. Both complete commands and guided selection use these
47
+ defaults without extra prompts. An unchanged or temporarily unavailable
48
+ subscription keeps the existing pool and bounded retry cadence. A recent
49
+ refresh can defer the next fetch; server Retry-After can defer it further.
50
+ These are not restoration-time guarantees.
51
+
52
+ Default selection evidence
53
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
54
+
55
+ A deterministic comparison used the real session scheduler/private provider
56
+ publication with injected network time: 1/5/10/20 nodes, five ordering seeds,
57
+ one working node, two-second fetches, and 1/3/5/8-second successful probes.
58
+ The reference replayed the recovery loop at ``7f40af8`` with its 300-second
59
+ refresh interval. Controller and process latency were not simulated; results
60
+ start at confirmed recovery, excluding failure detection.
61
+
62
+ For complete replacement with a one-second working node, the 3-second default
63
+ reduced sample P95 from 405 to 42 simulated seconds (maximum 54). For partial
64
+ failure with a three-second working node, sample P95 was 35 seconds, versus
65
+ 223 with a two-second fast budget and 55 with a five-second fast budget.
66
+ Three seconds is the smallest compared budget that accepts this moderately
67
+ slow route on the first sweep. It is a workload choice, not a universal optimum.
68
+ For five-second working nodes the fast sweep adds work: sample P95 was 245
69
+ seconds versus 105 in the reference. Normal-budget retries preserve recovery
70
+ in this case; users of consistently slow routes can increase the fast budget.
71
+
72
+ ``test/runtime/test_fast_recovery.py`` pins the default first-sweep bound for
73
+ 1--20 nodes with 1/3-second successful probes over five seeds, prompt complete
74
+ replacement, independent refresh even at round exhaustion, throttling and
75
+ normal-budget fallback. These model checks supplement the real protocol
76
+ data-plane suite; they do not replace it or imply public-network percentiles.
77
+
78
+ Selection policies
79
+ ------------------
80
+
81
+ * ``none`` stops after confirmed failure without restarting or refreshing.
82
+ * ``fixed`` retries only the initial node identity.
83
+ * ``random`` visits a shuffled pool without replacement before another sweep.
84
+ * ``adaptive`` uses session-local, aging success estimates and recovery-only
85
+ exploration; all eligible nodes must eventually receive an attempt.
86
+ * ``fallback`` composes the closed stages ``current``, ``adaptive`` and
87
+ ``random``. The default is ``current:1,adaptive:3,random:all``. Stage names
88
+ must be unique; counts are positive bounded integers or ``all``. Current
89
+ permits only one attempt. Candidates are deduplicated across stages.
90
+
91
+ Retry timing uses capped exponential backoff with jitter, separate node
92
+ cooldowns and refresh throttling. A brief success does not reset escalation;
93
+ only a stable healthy period does. No tight loop is allowed for exhausted,
94
+ unchanged, disabled or cooling-down pools.
95
+
96
+ Execution and outputs
97
+ ---------------------
98
+
99
+ The session keeps its home-wide lock, listener port and optional credentials
100
+ through degradation. Mihomo uses atomic private single-provider publication
101
+ and authenticated bounded reloads. Exact candidate acceptance, selection and
102
+ absence of direct bypass must be checked before connectivity can establish
103
+ readiness. Each control request has an absolute wall deadline covering response
104
+ headers and body, including slow trickles. A standard-library buffered reader
105
+ clamps each underlying socket read to the remaining time; no deadline worker
106
+ is allocated. Ambiguous control state, authentication, integrity, TLS, permission
107
+ and unsafe cleanup failures remain terminal. Health probes report certificate
108
+ validation failure and explicit HTTP 407 responses as closed terminal
109
+ verdicts, never as ordinary target outages. CONNECT 407 refusals are recognized
110
+ only through the pinned Requests/urllib3/standard-library exception chain and
111
+ the locally generated status prefix; arbitrary exception messages are never
112
+ searched or logged. Other proxy connection failures remain retryable. A real
113
+ loopback proxy refusal verifies classification across the health process
114
+ boundary. Confirmed child exit must not be confused with inability to stop a child.
115
+
116
+ Cache age requests a refresh but does not disqualify verified cached nodes.
117
+ Temporary refresh failure preserves the last good revision. Successful refresh
118
+ prunes removed identities and statistics; removing the fixed identity produces
119
+ an actionable error. Recovery refresh receives an independent budget and respects its
120
+ own minimum interval, backoff and server Retry-After. Retry-After is bounded
121
+ to one day; malformed values are discarded. Refresh starts no more often than
122
+ once per 60 seconds by default, doubles its delay after consecutive transport
123
+ failures up to one hour, and resets after success. Mandatory worker cleanup has
124
+ separate bounded stop intervals and must complete even after the network
125
+ budget expires; inability to prove cleanup is terminal. A standalone
126
+ subscription operation retains its original home lock while cleanup remains
127
+ unconfirmed. The same manager, used on its owning thread, may release that
128
+ retained lock on its next operation only after the supervisor confirms both worker termination and
129
+ artifact removal. A runtime session similarly refuses to announce stopped
130
+ or release its own lock while subscription cleanup is pending. No cleanup
131
+ thread releases a thread-owned FileLock or acquires a second home lock.
132
+ The subscription caller waits on a starter-owned completion event rather than
133
+ an interruptible thread join, which can incorrectly report a live starter as
134
+ stopped on older CPython versions. The cleanup supervisor also confirms actual
135
+ starter exit before removing the private worker directory.
136
+ Acquired operation locks remain strongly referenced until explicit exit, so
137
+ discarding a failed owner cannot release an unconfirmed operation through
138
+ garbage collection. Discarding such an owner forfeits in-process cleanup
139
+ recovery; the home stays locked until the process exits.
140
+
141
+ Sanitized events expose starting, degraded, retrying, ready and stopped states,
142
+ actual retry delays, skip reasons and current health. No event falsely reports
143
+ readiness or exposes secrets. Threads, children, statistics and recent logs
144
+ remain bounded for an indefinitely running session. Ctrl-C and SIGTERM must
145
+ cancel probes, refreshes and backoff and complete safe cleanup. The CLI owns
146
+ SIGINT and SIGTERM handlers only during the foreground session. The first
147
+ signal requests unwinding; repeated signals are ignored until cleanup has
148
+ finished, then prior handlers are restored. Successful cancellation exits
149
+ with 128 plus the signal number. Cleanup failure remains a terminal error.
150
+
151
+ Lifecycle events use a separate optional event callback. JSONL emits these
152
+ events on stdout and ordinary logs on stderr, independent of log-level
153
+ filtering. The session writes the same bounded event summary to its private
154
+ log. Each event includes a closed reason code, attempt and round counters,
155
+ candidate count, last healthy effective node, loaded node, attempted node,
156
+ current quorum and actual next delay. Startup emits ready only after access
157
+ publication; recovery emits ready only after acceptance and quorum. Stopped
158
+ is emitted only after child and artifact cleanup succeeds, while the home
159
+ lock still protects the event log write. Refresh events preserve the current
160
+ state and distinguish stale cache, unchanged content, updated content and
161
+ transient transport failure. Repeated stop is
162
+ idempotent. A closed output stream does not interrupt service.
163
+
164
+ Default network checks run in one disposable spawned process with at most
165
+ three request threads. The parent includes process startup in the check
166
+ budget, terminates the process on timeout or interruption, and confirms exit
167
+ before accepting another batch. Credentials travel through multiprocessing
168
+ IPC rather than command arguments or files. Results use a bounded, validated
169
+ JSON envelope with closed diagnostic codes. Cleanup retains a separate bounded
170
+ budget and fails closed on uncertain process ownership. Injected transports
171
+ run in-process for deterministic testing. Library scripts that launch default
172
+ probes must use the standard ``if __name__ == "__main__"`` entry guard
173
+ required by multiprocessing spawn; the CLI already provides that guard.
174
+ The installed ``self-check`` exercises the actual spawned health worker against
175
+ a temporary loopback HTTP server. It requires a successful round trip and
176
+ confirmed cleanup; standalone artifact CI runs this check on each target OS.
177
+
178
+ Injected in-process checks allocate at most three workers. If a request outlives
179
+ a check's budget, subsequent checks report it as unfinished and allocate no new
180
+ workers until that batch finishes. Late results do not establish readiness for
181
+ a later check. Cancellation prevents pending targets from starting. Completion
182
+ is tracked with worker-owned events instead of interruptible joins; cleanup
183
+ must confirm all workers have exited before releasing the home lock. An
184
+ unconfirmed worker makes cleanup fail closed. This bounds worker accumulation but does not by itself prove
185
+ that an arbitrary injected transport can be cancelled. Default network
186
+ transports instead use the disposable process described above. Native platform
187
+ and packaged-executable verification run in the repository CI matrix.
188
+
189
+ Runtime logs retain recent diagnostics within a 4 MiB file. Both producers
190
+ serialize writes under the existing shared lock. Descriptors use binary mode
191
+ on Windows so byte bounds and compaction offsets are not changed by newline
192
+ translation. On overflow they discard
193
+ the oldest portion, retain complete recent lines from the final half and
194
+ append the new redacted line through the same validated descriptor. No
195
+ rotation paths are created. A crash during this in-place compaction can lose
196
+ diagnostic history; it cannot modify managed configuration or credentials.
197
+
198
+ Verification required before merge
199
+ ----------------------------------
200
+
201
+ Tests are written before behavior. Deterministic scenarios cover startup
202
+ offline then online, outages longer than 120 seconds, all nodes unavailable,
203
+ one working alternate, subscription scope, fixed identity, no healthy
204
+ switching, hundreds of candidates, cooldowns, unchanged and failing refresh,
205
+ old usable cache, removed fixed identity, flapping and cancellation at each
206
+ blocking boundary. Adversarial reload tests cover empty and malicious
207
+ providers, stale accepted content, authorization and rollback failures.
208
+
209
+ Real qualified-backend data-plane tests cover every allowed protocol and
210
+ container, including hot switches with stable listener and credentials.
211
+ Long-run tests verify bounded workers, logs and statistics. Existing secret
212
+ matrices must include new output channels. Explicit and guided CLI behavior
213
+ must agree; rendered help is checked at 72, 80, 100 and 120 columns.
214
+
215
+ All changed or affected functions require 100 percent branch coverage,
216
+ including native platform evidence when necessary, without exclusion pragmas
217
+ or a whole-repository average substituting for the affected-area audit.
218
+ Python 3.7 compatibility, normal test gates, generated API documentation,
219
+ documentation build and package build must pass. The PR body is English;
220
+ completion requires review and CI evidence that the full scope is merge-ready.