meshcode 2.11.11__tar.gz → 2.11.12__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 (223) hide show
  1. {meshcode-2.11.11 → meshcode-2.11.12}/PKG-INFO +1 -1
  2. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/comms_v4.py +109 -51
  4. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode.egg-info/SOURCES.txt +1 -0
  6. {meshcode-2.11.11 → meshcode-2.11.12}/pyproject.toml +1 -1
  7. meshcode-2.11.12/tests/test_init_device_code.py +68 -0
  8. {meshcode-2.11.11 → meshcode-2.11.12}/README.md +0 -0
  9. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/__main__.py +0 -0
  10. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/_stop_hook_template.py +0 -0
  11. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/ascii_art.py +0 -0
  12. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/cli.py +0 -0
  13. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/compat.py +0 -0
  14. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/daemon.py +0 -0
  15. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/doctor.py +0 -0
  16. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/error_hints.py +0 -0
  17. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/exceptions.py +0 -0
  18. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/invites.py +0 -0
  19. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/launcher.py +0 -0
  20. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/launcher_install.py +0 -0
  21. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/__init__.py +0 -0
  22. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/__main__.py +0 -0
  23. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/backend.py +0 -0
  24. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/realtime.py +0 -0
  25. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/server.py +0 -0
  26. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  27. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/test_backend.py +0 -0
  28. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  29. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  30. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  31. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  32. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  33. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/preferences.py +0 -0
  34. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/protocol_handler.py +0 -0
  35. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/protocol_v2.py +0 -0
  36. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/quickstart.py +0 -0
  37. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/run_agent.py +0 -0
  38. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/scripts/check_secrets.py +0 -0
  39. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/scripts/race_rate_harness.py +0 -0
  40. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/secrets.py +0 -0
  41. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/self_update.py +0 -0
  42. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/setup_clients.py +0 -0
  43. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/supervisor.py +0 -0
  44. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode/upload.py +0 -0
  45. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/comms_v4.py +0 -0
  46. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  47. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  48. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/cli.py +0 -0
  49. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  50. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/compat.py +0 -0
  51. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  52. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  53. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/invites.py +0 -0
  54. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  55. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  56. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  57. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  58. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  59. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  60. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  61. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  62. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  63. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  64. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  65. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  66. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  67. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  68. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  69. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  70. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  71. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  72. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/meshcode/upload.py +0 -0
  73. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  74. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_core.py +0 -0
  75. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  76. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  77. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  78. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  79. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  80. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  81. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  82. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  83. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  84. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  85. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  86. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  87. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  88. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  89. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  90. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  91. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  92. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  93. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  94. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  95. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  96. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  97. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  98. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  99. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  100. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  101. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  102. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  103. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  104. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  105. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  106. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  107. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  108. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  109. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  110. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  111. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  112. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  113. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/comms_v4.py +0 -0
  114. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  115. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  116. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/cli.py +0 -0
  117. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  118. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/compat.py +0 -0
  119. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  120. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  121. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/invites.py +0 -0
  122. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  123. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  124. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  125. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  126. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  127. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  128. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  129. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  130. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  131. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  132. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  133. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  134. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  135. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  136. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  137. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  138. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  139. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  140. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/meshcode/upload.py +0 -0
  141. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  142. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_core.py +0 -0
  143. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  144. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  145. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  146. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  147. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  148. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  149. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  150. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  151. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  152. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  153. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  154. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/comms_v4.py +0 -0
  155. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  156. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  157. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  158. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  159. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  160. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  161. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  162. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  163. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  164. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  165. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  166. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  167. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  168. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  169. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  170. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  171. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  172. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  173. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  174. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  175. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  176. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  177. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  178. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  179. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  180. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  181. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  182. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  183. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_core.py +0 -0
  184. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  185. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  186. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  187. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  188. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  189. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  190. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  191. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  192. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  193. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  194. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  195. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode.egg-info/dependency_links.txt +0 -0
  196. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode.egg-info/entry_points.txt +0 -0
  197. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode.egg-info/requires.txt +0 -0
  198. {meshcode-2.11.11 → meshcode-2.11.12}/meshcode.egg-info/top_level.txt +0 -0
  199. {meshcode-2.11.11 → meshcode-2.11.12}/setup.cfg +0 -0
  200. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_auto_update_hardening.py +0 -0
  201. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_boot_bug_regression.py +0 -0
  202. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_color_truecolor.py +0 -0
  203. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_core.py +0 -0
  204. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_cross_agent_messaging.py +0 -0
  205. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_doctor.py +0 -0
  206. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_epistemic_v1_python_sdk.py +0 -0
  207. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  208. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_esc_deaf_state.py +0 -0
  209. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_exceptions.py +0 -0
  210. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_install_guard.py +0 -0
  211. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_lease_sigterm_release.py +0 -0
  212. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_mark_read_batch.py +0 -0
  213. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_migration_integrity.py +0 -0
  214. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_realtime_event_freshness.py +0 -0
  215. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_rls_cross_tenant.py +0 -0
  216. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_rpc_migrations.py +0 -0
  217. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_security_regressions.py +0 -0
  218. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_sentinel.py +0 -0
  219. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_setup_path.py +0 -0
  220. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_sleep_signals.py +0 -0
  221. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_status_enum_coverage.py +0 -0
  222. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_stay_on_loop_hook.py +0 -0
  223. {meshcode-2.11.11 → meshcode-2.11.12}/tests/test_wait_open_tasks_contradiction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.11
3
+ Version: 2.11.12
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.11.11"
2
+ __version__ = "2.11.12"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -2777,26 +2777,108 @@ if __name__ == "__main__":
2777
2777
  sys.exit(1)
2778
2778
  print()
2779
2779
 
2780
- # B3: wrap pairing RPC so SSL / network errors abort cleanly (no
2781
- # silent fall-through to API-key paste — friction #7).
2780
+ # B3: wrap any pairing RPC so SSL / network errors abort cleanly with
2781
+ # an actionable message (no silent fall-through, friction #7).
2782
+ def _pairing_rpc(fn, args):
2783
+ try:
2784
+ return sb_rpc(fn, args)
2785
+ except Exception as _e:
2786
+ _msg = str(_e).lower()
2787
+ if "certificate" in _msg or "ssl" in _msg:
2788
+ print()
2789
+ print(" [meshcode] SSL certificate verification failed.")
2790
+ print(" [meshcode] This usually means your Python install is missing root certs.")
2791
+ _v = sys.version_info
2792
+ print(f" [meshcode] Fix: run /Applications/Python\\ {_v.major}.{_v.minor}/Install\\ Certificates.command")
2793
+ print(f" [meshcode] (Replace {_v.major}.{_v.minor} with your actual installed version.)")
2794
+ print(f" [meshcode] Alternative: pip install --upgrade certifi")
2795
+ else:
2796
+ print()
2797
+ print(f" [meshcode] Pairing service unreachable: {_e}")
2798
+ print(f" [meshcode] Check your network, then re-run `meshcode init`.")
2799
+ sys.exit(1)
2800
+
2801
+ # B6.2 device-code OAuth (preferred): generates a code, opens browser
2802
+ # to /auth/device?code=…, user clicks Approve, CLI receives a scoped
2803
+ # token. Token is per-device, revocable from dashboard. Replaces the
2804
+ # legacy api-key paste path (which left long-lived secrets in
2805
+ # terminal history — Samuel friction).
2806
+ import hashlib as _hashlib
2807
+ import platform as _platform
2782
2808
  try:
2783
- pairing = sb_rpc("mc_create_pairing_session", {})
2784
- except Exception as _init_e:
2785
- _msg = str(_init_e).lower()
2786
- if "certificate" in _msg or "ssl" in _msg:
2809
+ _hn = _platform.node() or "unknown"
2810
+ _device_fp = _hashlib.sha256(
2811
+ f"{_platform.system()}|{_hn}|{_platform.machine()}".encode()
2812
+ ).hexdigest()[:32]
2813
+ except Exception:
2814
+ _device_fp = _hashlib.sha256(b"meshcode-anon-device").hexdigest()[:32]
2815
+ _device_name = f"{_platform.node() or 'device'} ({_platform.system()})"
2816
+
2817
+ b6_resp = _pairing_rpc("mc_device_code_create", {
2818
+ "p_device_fingerprint": _device_fp,
2819
+ "p_device_name": _device_name,
2820
+ })
2821
+ if isinstance(b6_resp, dict) and b6_resp.get("ok") and b6_resp.get("code"):
2822
+ code = b6_resp["code"]
2823
+ expires_in = int(b6_resp.get("expires_in_s") or 600)
2824
+ url = f"https://meshcode.io/auth/device?code={code}"
2825
+ print(f" Step 1: Confirm the code in your browser:")
2826
+ print()
2827
+ print(f" ┌─────────────────┐")
2828
+ print(f" │ {code:^11} │")
2829
+ print(f" └─────────────────┘")
2830
+ print()
2831
+ print(f" Opening {url} ...")
2832
+ print(f" (If browser doesn't open: visit https://meshcode.io/auth/device)")
2833
+ print()
2834
+ try:
2835
+ webbrowser.open(url)
2836
+ except Exception:
2837
+ pass
2838
+ print(" Waiting for approval", end="", flush=True)
2839
+ token = None
2840
+ deadline = _t.time() + expires_in
2841
+ last_status = "pending"
2842
+ while _t.time() < deadline:
2843
+ _t.sleep(2)
2844
+ print(".", end="", flush=True)
2845
+ poll = _pairing_rpc("mc_device_code_poll", {
2846
+ "p_code": code,
2847
+ "p_device_fingerprint": _device_fp,
2848
+ })
2849
+ if not (isinstance(poll, dict)):
2850
+ continue
2851
+ if poll.get("status") == "approved" and poll.get("token"):
2852
+ token = poll["token"]
2853
+ break
2854
+ if poll.get("status") in ("expired", "consumed", "rejected") or poll.get("error") not in (None, "rate_limited"):
2855
+ last_status = poll.get("status") or poll.get("error")
2856
+ break
2857
+ print()
2858
+ if token:
2859
+ login(token)
2787
2860
  print()
2788
- print(" [meshcode] SSL certificate verification failed.")
2789
- print(" [meshcode] This usually means your Python install is missing root certs.")
2790
- _v = sys.version_info
2791
- print(f" [meshcode] Fix: run /Applications/Python\\ {_v.major}.{_v.minor}/Install\\ Certificates.command")
2792
- print(f" [meshcode] (Replace {_v.major}.{_v.minor} with your actual installed version.)")
2793
- print(f" [meshcode] Alternative: pip install --upgrade certifi")
2794
- else:
2861
+ print(" Paired successfully device added to your account.")
2862
+ print(" Step 2: Create your first meshwork")
2863
+ print(" Run: meshcode go <agent-name> --project <meshwork-name>")
2795
2864
  print()
2796
- print(f" [meshcode] Pairing service unreachable: {_init_e}")
2797
- print(f" [meshcode] Check your network, then re-run `meshcode init`.")
2865
+ print(" Example:")
2866
+ print(" meshcode go backend --project my-app")
2867
+ print()
2868
+ sys.exit(0)
2869
+ print()
2870
+ print(f" Pairing did not complete ({last_status}). Re-run: meshcode init")
2798
2871
  sys.exit(1)
2799
- if pairing and isinstance(pairing, dict) and pairing.get("ok"):
2872
+
2873
+ # Legacy fallback: if mc_device_code_create returned a function-not-found
2874
+ # error (B6.1 mig 326 not yet applied on this Supabase project), drop
2875
+ # back to the older mc_create_pairing_session flow. Manual API-key paste
2876
+ # has been retired (security — friction #6).
2877
+ _legacy_b6_err = ""
2878
+ if isinstance(b6_resp, dict):
2879
+ _legacy_b6_err = str(b6_resp.get("error") or "")
2880
+ pairing = _pairing_rpc("mc_create_pairing_session", {})
2881
+ if isinstance(pairing, dict) and pairing.get("ok"):
2800
2882
  session_id = pairing["session_id"]
2801
2883
  code = pairing["code"]
2802
2884
  url = pairing["url"]
@@ -2811,11 +2893,11 @@ if __name__ == "__main__":
2811
2893
  pass
2812
2894
  print(" Waiting for approval", end="", flush=True)
2813
2895
  api_key = None
2814
- for _ in range(150): # 150 * 2s = 5 minutes
2896
+ for _ in range(150):
2815
2897
  _t.sleep(2)
2816
2898
  print(".", end="", flush=True)
2817
- poll = sb_rpc("mc_poll_pairing_session", {"p_session_id": session_id})
2818
- if poll and isinstance(poll, dict):
2899
+ poll = _pairing_rpc("mc_poll_pairing_session", {"p_session_id": session_id})
2900
+ if isinstance(poll, dict):
2819
2901
  if poll.get("status") == "approved" and poll.get("api_key"):
2820
2902
  api_key = poll["api_key"]
2821
2903
  break
@@ -2823,46 +2905,22 @@ if __name__ == "__main__":
2823
2905
  break
2824
2906
  print()
2825
2907
  if api_key:
2826
- print()
2827
2908
  login(api_key)
2828
2909
  print()
2829
2910
  print(" Step 2: Create your first meshwork")
2830
2911
  print(" Run: meshcode go <agent-name> --project <meshwork-name>")
2831
2912
  print()
2832
- print(" Example:")
2833
- print(" meshcode go backend --project my-app")
2834
- print()
2835
2913
  sys.exit(0)
2836
- else:
2837
- print(" Pairing timed out or was not approved.")
2838
- print()
2839
-
2840
- # Fallback: manual API key paste
2841
- print(" Step 1: Create your account at meshcode.io")
2842
- try:
2843
- webbrowser.open("https://meshcode.io")
2844
- except Exception:
2845
- print(" Visit: https://meshcode.io")
2846
- print(" Step 2: Copy your API key from Settings")
2847
- print()
2848
- try:
2849
- api_key = input(" Paste your API key (mc_...): ").strip()
2850
- except (EOFError, KeyboardInterrupt):
2851
- api_key = ""
2852
- print()
2853
- if api_key:
2854
- login(api_key)
2855
- print()
2856
- print(" Step 3: Create your first meshwork")
2857
- print(" Run: meshcode go <agent-name> --project <meshwork-name>")
2858
2914
  print()
2859
- print(" Example:")
2860
- print(" meshcode go backend --project my-app")
2861
- print()
2862
- else:
2863
- print(" [meshcode] No API key provided. Run: meshcode login <api_key>")
2915
+ print(f" Pairing did not complete. Re-run: meshcode init")
2864
2916
  sys.exit(1)
2865
- sys.exit(0)
2917
+
2918
+ # Both paths failed.
2919
+ print()
2920
+ print(f" [meshcode] Pairing unavailable: device-code ({_legacy_b6_err or 'unknown'}); "
2921
+ f"legacy pairing ({pairing.get('error') if isinstance(pairing, dict) else 'unknown'}).")
2922
+ print(f" [meshcode] Re-run `meshcode init` later or contact support.")
2923
+ sys.exit(1)
2866
2924
 
2867
2925
  # Auth guard: commands that talk to Supabase need a valid API key.
2868
2926
  # doctor, help, version, login, prefs, launcher don't need auth.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.11
3
+ Version: 2.11.12
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -204,6 +204,7 @@ tests/test_epistemic_v1_python_sdk.py
204
204
  tests/test_epistemic_v1_stop_conditions.py
205
205
  tests/test_esc_deaf_state.py
206
206
  tests/test_exceptions.py
207
+ tests/test_init_device_code.py
207
208
  tests/test_install_guard.py
208
209
  tests/test_lease_sigterm_release.py
209
210
  tests/test_mark_read_batch.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.11.11"
7
+ version = "2.11.12"
8
8
  description = "Real-time communication between AI agents — Supabase-backed CLI"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -0,0 +1,68 @@
1
+ """Tests for B6.2 — device-code OAuth flow in `meshcode init`.
2
+
3
+ The full init() flow is tightly coupled to comms_v4's main() dispatch and
4
+ has side effects (sys.exit, webbrowser, input, supabase). Rather than spin
5
+ up subprocesses with monkey-patches that don't survive runpy re-imports,
6
+ this module verifies the *contracts* and the small helpers — the integration
7
+ is exercised by the live RPC handshake in production.
8
+ """
9
+ import hashlib
10
+ import platform
11
+
12
+
13
+ def test_device_fingerprint_is_stable():
14
+ """Same machine -> same fingerprint across calls (init can't pair if it
15
+ drifts mid-session)."""
16
+ def _fp():
17
+ try:
18
+ hn = platform.node() or "unknown"
19
+ return hashlib.sha256(
20
+ f"{platform.system()}|{hn}|{platform.machine()}".encode()
21
+ ).hexdigest()[:32]
22
+ except Exception:
23
+ return hashlib.sha256(b"meshcode-anon-device").hexdigest()[:32]
24
+
25
+ a = _fp()
26
+ b = _fp()
27
+ assert a == b
28
+ assert len(a) == 32
29
+ # Hex string
30
+ assert all(c in "0123456789abcdef" for c in a)
31
+
32
+
33
+ def test_init_branch_has_no_apikey_paste_prompt():
34
+ """Source-level invariant: comms_v4.py 'cmd == init' block must not call
35
+ builtins.input() for the API key (security regression sentinel)."""
36
+ import pathlib
37
+ src = pathlib.Path("meshcode/comms_v4.py").read_text()
38
+ init_idx = src.find('if cmd == "init":')
39
+ assert init_idx >= 0
40
+ # Find the next top-level `elif cmd ==` or `if cmd not in _NO_AUTH_CMDS`
41
+ end_idx = min(
42
+ i for i in (
43
+ src.find("if cmd not in _NO_AUTH_CMDS:", init_idx + 1),
44
+ src.find("elif cmd == ", init_idx + 1),
45
+ ) if i > 0
46
+ )
47
+ init_block = src[init_idx:end_idx]
48
+ # Must not contain input("Paste your API key") or similar paste prompts
49
+ paste_prompts = ['Paste your API key', 'input(" Paste']
50
+ for p in paste_prompts:
51
+ assert p not in init_block, (
52
+ f"init block must not contain {p!r} — B6.2 security goal "
53
+ "(no terminal paste of long-lived secrets)"
54
+ )
55
+
56
+
57
+ def test_init_branch_calls_device_code_first():
58
+ """Source-level: device-code RPC must be called BEFORE legacy pairing."""
59
+ import pathlib
60
+ src = pathlib.Path("meshcode/comms_v4.py").read_text()
61
+ init_idx = src.find('if cmd == "init":')
62
+ end_idx = src.find("if cmd not in _NO_AUTH_CMDS:", init_idx)
63
+ init_block = src[init_idx:end_idx]
64
+ dc_idx = init_block.find("mc_device_code_create")
65
+ legacy_idx = init_block.find("mc_create_pairing_session")
66
+ assert dc_idx > 0, "init must call mc_device_code_create"
67
+ assert legacy_idx > 0, "init must keep mc_create_pairing_session fallback"
68
+ assert dc_idx < legacy_idx, "device-code must be tried before legacy"
File without changes
File without changes