msgctl 0.2.6__tar.gz → 0.2.8__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 (754) hide show
  1. {msgctl-0.2.6 → msgctl-0.2.8}/CHANGELOG.md +11 -0
  2. {msgctl-0.2.6 → msgctl-0.2.8}/PKG-INFO +8 -3
  3. {msgctl-0.2.6 → msgctl-0.2.8}/README.md +6 -2
  4. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CLIENT_CONNECTIONS.md +9 -9
  5. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CLIENT_INSTALLATION.md +4 -4
  6. {msgctl-0.2.6 → msgctl-0.2.8}/docs/FILESYSTEM_LAYOUT.md +22 -6
  7. msgctl-0.2.8/docs/YUBIKEY.md +73 -0
  8. msgctl-0.2.8/docs/YUBIKEY_CASE.md +37 -0
  9. {msgctl-0.2.6 → msgctl-0.2.8}/docs/YUBIKEY_DESIGN.md +1 -1
  10. {msgctl-0.2.6 → msgctl-0.2.8}/docs/post-universe.md +82 -0
  11. {msgctl-0.2.6 → msgctl-0.2.8}/packaging/build-native.py +3 -3
  12. {msgctl-0.2.6 → msgctl-0.2.8}/pyproject.toml +2 -1
  13. {msgctl-0.2.6 → msgctl-0.2.8}/pyproject.toml.orig +2 -1
  14. msgctl-0.2.8/scripts/check_nebula_browser.py +478 -0
  15. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/__init__.py +1 -1
  16. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/cli.py +27 -2
  17. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client.py +92 -9
  18. msgctl-0.2.8/src/msg/client_accounts.py +77 -0
  19. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_agent_cli.py +4 -1
  20. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_connection.py +1 -0
  21. msgctl-0.2.8/src/msg/client_yubikey.py +467 -0
  22. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web-app.js +150 -39
  23. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web-model.js +68 -8
  24. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web-renderer.js +189 -242
  25. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web.css +89 -34
  26. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web.html +24 -8
  27. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/paths.py +80 -12
  28. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/bot_feed.py +7 -1
  29. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/communication.py +9 -4
  30. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/discovery.py +8 -0
  31. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/mail_views.py +3 -0
  32. msgctl-0.2.8/src/msg/plugins/star_projection.py +105 -0
  33. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/browser_style.py +6 -1
  34. msgctl-0.2.8/src/msg/transports/discovery_pages.py +87 -0
  35. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/home_page.py +8 -3
  36. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/http_routes.py +100 -4
  37. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/universe.py +69 -3
  38. msgctl-0.2.8/tests/js/nebula.test.cjs +86 -0
  39. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_bounty.py +3 -0
  40. msgctl-0.2.8/tests/test_client_accounts.py +156 -0
  41. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_paths.py +16 -5
  42. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_subagents_remote.py +24 -5
  43. msgctl-0.2.8/tests/test_client_yubikey.py +184 -0
  44. msgctl-0.2.8/tests/test_discovery_pages.py +86 -0
  45. msgctl-0.2.8/tests/test_mailbox_contacts.py +80 -0
  46. msgctl-0.2.8/tests/test_star_projection.py +205 -0
  47. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_todo_due_inbox.py +4 -0
  48. {msgctl-0.2.6 → msgctl-0.2.8}/uv.lock +173 -1
  49. {msgctl-0.2.6 → msgctl-0.2.8}/.python-version +0 -0
  50. {msgctl-0.2.6 → msgctl-0.2.8}/CONTRIBUTING.md +0 -0
  51. {msgctl-0.2.6 → msgctl-0.2.8}/SECURITY.md +0 -0
  52. {msgctl-0.2.6 → msgctl-0.2.8}/conformance/test_token_budget.py +0 -0
  53. {msgctl-0.2.6 → msgctl-0.2.8}/conformance/test_transports.py +0 -0
  54. {msgctl-0.2.6 → msgctl-0.2.8}/conftest.py +0 -0
  55. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/README.md +0 -0
  56. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/hosting-role.sql +0 -0
  57. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/hosting.example.toml +0 -0
  58. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/mail.example.toml +0 -0
  59. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/msgd-hosting.service +0 -0
  60. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/msgd-worker.service +0 -0
  61. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/msgd-worker@.service +0 -0
  62. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/msgd.service +0 -0
  63. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/msgd@.service +0 -0
  64. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/nginx-shared-http-logging.conf +0 -0
  65. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/nginx.conf +0 -0
  66. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/prepare-hosting-content.sh +0 -0
  67. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/prepare-instance.sh +0 -0
  68. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/prepare-service.sh +0 -0
  69. {msgctl-0.2.6 → msgctl-0.2.8}/deploy/sshd_config +0 -0
  70. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ARCHITECTURE.md +0 -0
  71. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ARCHITECTURE_PROGRESS_20260929.md +0 -0
  72. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ARCHITECTURE_REUSE.md +0 -0
  73. {msgctl-0.2.6 → msgctl-0.2.8}/docs/AUTHORIZATION_SOURCES.md +0 -0
  74. {msgctl-0.2.6 → msgctl-0.2.8}/docs/BOUNTY_ACCEPTANCE.md +0 -0
  75. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CLIENT_BOUNDARY_PROGRESS.md +0 -0
  76. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CLIENT_PART_BYTES_PROGRESS.md +0 -0
  77. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CLI_FIELD_SELECTION.md +0 -0
  78. {msgctl-0.2.6 → msgctl-0.2.8}/docs/COMPLETE_RECOVERY_PROOF.md +0 -0
  79. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CREDENTIAL_DELIVERY.md +0 -0
  80. {msgctl-0.2.6 → msgctl-0.2.8}/docs/CUSTODIAL_HISTORY.md +0 -0
  81. {msgctl-0.2.6 → msgctl-0.2.8}/docs/C_READ_ACCEPTANCE.md +0 -0
  82. {msgctl-0.2.6 → msgctl-0.2.8}/docs/DEPLOYMENT.md +0 -0
  83. {msgctl-0.2.6 → msgctl-0.2.8}/docs/DESIGN_CHANGE_REQUESTS.md +0 -0
  84. {msgctl-0.2.6 → msgctl-0.2.8}/docs/DESIGN_CONTRACT_INVENTORY.md +0 -0
  85. {msgctl-0.2.6 → msgctl-0.2.8}/docs/FOLLOW_AND_FEED.md +0 -0
  86. {msgctl-0.2.6 → msgctl-0.2.8}/docs/GIT_BOUNDARY_PROGRESS.md +0 -0
  87. {msgctl-0.2.6 → msgctl-0.2.8}/docs/HOSTING_AUTHORITY_PROGRESS.md +0 -0
  88. {msgctl-0.2.6 → msgctl-0.2.8}/docs/HOSTING_RUNTIME.md +0 -0
  89. {msgctl-0.2.6 → msgctl-0.2.8}/docs/HOSTING_RUNTIME_PROGRESS.md +0 -0
  90. {msgctl-0.2.6 → msgctl-0.2.8}/docs/IMPLEMENTATION_STATUS.md +0 -0
  91. {msgctl-0.2.6 → msgctl-0.2.8}/docs/INTEGRATION_PROGRESS_20260929.md +0 -0
  92. {msgctl-0.2.6 → msgctl-0.2.8}/docs/INTEGRATION_REGRESSION_PROGRESS.md +0 -0
  93. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ISSUES_68_70_PROGRESS.md +0 -0
  94. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ISSUES_78_80_PROGRESS.md +0 -0
  95. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ISSUE_PROGRESS.md +0 -0
  96. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ISSUE_RESOLUTION.md +0 -0
  97. {msgctl-0.2.6 → msgctl-0.2.8}/docs/ITERATION_PLAN.md +0 -0
  98. {msgctl-0.2.6 → msgctl-0.2.8}/docs/LEDGER_MIGRATION.md +0 -0
  99. {msgctl-0.2.6 → msgctl-0.2.8}/docs/LEGACY_GIT_MIGRATION.md +0 -0
  100. {msgctl-0.2.6 → msgctl-0.2.8}/docs/LEGACY_IDENTITY_ARCHIVE.md +0 -0
  101. {msgctl-0.2.6 → msgctl-0.2.8}/docs/LEGACY_SQLITE_PRESERVATION.md +0 -0
  102. {msgctl-0.2.6 → msgctl-0.2.8}/docs/LOCAL_VERIFICATION.md +0 -0
  103. {msgctl-0.2.6 → msgctl-0.2.8}/docs/MANAGED_CHECKOUT.md +0 -0
  104. {msgctl-0.2.6 → msgctl-0.2.8}/docs/MARKET_BOUNDARY_PROGRESS.md +0 -0
  105. {msgctl-0.2.6 → msgctl-0.2.8}/docs/MARKET_CLEARING.md +0 -0
  106. {msgctl-0.2.6 → msgctl-0.2.8}/docs/MARKET_CONTRACTS.md +0 -0
  107. {msgctl-0.2.6 → msgctl-0.2.8}/docs/METADATA_SESSION_PROGRESS.md +0 -0
  108. {msgctl-0.2.6 → msgctl-0.2.8}/docs/NATIVE_PACKAGES.md +0 -0
  109. {msgctl-0.2.6 → msgctl-0.2.8}/docs/NEW_ROOT_LEGACY_IMPORT_RUNBOOK.md +0 -0
  110. {msgctl-0.2.6 → msgctl-0.2.8}/docs/OAUTH.md +0 -0
  111. {msgctl-0.2.6 → msgctl-0.2.8}/docs/OFFER_ORDER_COMPATIBILITY.md +0 -0
  112. {msgctl-0.2.6 → msgctl-0.2.8}/docs/OFFER_RESOURCE_MIGRATION.md +0 -0
  113. {msgctl-0.2.6 → msgctl-0.2.8}/docs/POST_SUMMARIES.md +0 -0
  114. {msgctl-0.2.6 → msgctl-0.2.8}/docs/PROTOCOLS.md +0 -0
  115. {msgctl-0.2.6 → msgctl-0.2.8}/docs/QUALITY_PROGRESS.md +0 -0
  116. {msgctl-0.2.6 → msgctl-0.2.8}/docs/READ_ENTRY_ACCEPTANCE.md +0 -0
  117. {msgctl-0.2.6 → msgctl-0.2.8}/docs/RELEASE_ACCEPTANCE.md +0 -0
  118. {msgctl-0.2.6 → msgctl-0.2.8}/docs/SAVED_QUERIES.md +0 -0
  119. {msgctl-0.2.6 → msgctl-0.2.8}/docs/SEARCH_QUERY_V5.md +0 -0
  120. {msgctl-0.2.6 → msgctl-0.2.8}/docs/SERVICE_ALIASES.md +0 -0
  121. {msgctl-0.2.6 → msgctl-0.2.8}/docs/SSH_GIT_LOCAL_ACCEPTANCE.md +0 -0
  122. {msgctl-0.2.6 → msgctl-0.2.8}/docs/SUBAGENTS.md +0 -0
  123. {msgctl-0.2.6 → msgctl-0.2.8}/docs/SUBAGENT_ACCEPTANCE_20261001.md +0 -0
  124. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TASK_A_RECOVERY_20260928.md +0 -0
  125. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TASK_A_VERIFICATION.md +0 -0
  126. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TASK_C_EVIDENCE.md +0 -0
  127. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TEMPORARY_UPGRADE.md +0 -0
  128. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TERMINAL_DEMO.md +0 -0
  129. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TOKEN_DELIVERY_BOUNDARY_PROGRESS.md +0 -0
  130. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TOOL_RUNNER_BOUNDARY.md +0 -0
  131. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TRANSFER_STATUS_PROGRESS.md +0 -0
  132. {msgctl-0.2.6 → msgctl-0.2.8}/docs/TRUST_PATHS.md +0 -0
  133. {msgctl-0.2.6 → msgctl-0.2.8}/docs/VERIFICATION.md +0 -0
  134. {msgctl-0.2.6 → msgctl-0.2.8}/docs/WEBSUB.md +0 -0
  135. {msgctl-0.2.6 → msgctl-0.2.8}/docs/issue-75-77-local-verification.md +0 -0
  136. {msgctl-0.2.6 → msgctl-0.2.8}/docs/registry-template-tool-contracts.md +0 -0
  137. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/audit_filesystem_paths.py +0 -0
  138. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/check_client_install.py +0 -0
  139. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/check_installed_server.py +0 -0
  140. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/check_isolated_sshd.py +0 -0
  141. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/check_package_artifacts.py +0 -0
  142. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/check_tool_sandbox.py +0 -0
  143. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/check_universe_browser.py +0 -0
  144. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/ci_shards.py +0 -0
  145. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/render_terminal_demo.py +0 -0
  146. {msgctl-0.2.6 → msgctl-0.2.8}/scripts/verify_local.py +0 -0
  147. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/__init__.py +0 -0
  148. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/accounts.py +0 -0
  149. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/backup_retirement.py +0 -0
  150. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/backups.py +0 -0
  151. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/config_check.py +0 -0
  152. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/content_edit_check.py +0 -0
  153. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/custodial_check.py +0 -0
  154. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/diagnostics.py +0 -0
  155. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/dm_check.py +0 -0
  156. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/git_check.py +0 -0
  157. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/honor_check.py +0 -0
  158. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/legacy_approval.py +0 -0
  159. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/market.py +0 -0
  160. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/market_check.py +0 -0
  161. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/money.py +0 -0
  162. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/offer_import.py +0 -0
  163. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/preflight.py +0 -0
  164. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/recovery_policy.py +0 -0
  165. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/recovery_proof.py +0 -0
  166. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/recovery_replay.py +0 -0
  167. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/recovery_state.py +0 -0
  168. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/restore_database.py +0 -0
  169. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/root.py +0 -0
  170. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/rotation.py +0 -0
  171. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/token_delivery_check.py +0 -0
  172. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/tool_check.py +0 -0
  173. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/transfer_check.py +0 -0
  174. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/admin/upgrade_check.py +0 -0
  175. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/.github/workflows/test.yml +0 -0
  176. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/.gitignore +0 -0
  177. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/LICENSE +0 -0
  178. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/README.md +0 -0
  179. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/README.zh-CN.md +0 -0
  180. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/__init__.py +0 -0
  181. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/pyproject.toml +0 -0
  182. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/ranker.py +0 -0
  183. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/algorithm/tests/test_ranker.py +0 -0
  184. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/application.py +0 -0
  185. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/atomic_file.py +0 -0
  186. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/bootstrap.py +0 -0
  187. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_api_keys.py +0 -0
  188. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_certificates.py +0 -0
  189. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_collaboration.py +0 -0
  190. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_content.py +0 -0
  191. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_custodial.py +0 -0
  192. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_listener.py +0 -0
  193. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_market.py +0 -0
  194. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_oauth.py +0 -0
  195. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_output.py +0 -0
  196. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_recovery.py +0 -0
  197. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_secrets.py +0 -0
  198. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_subagents.py +0 -0
  199. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_subagents_remote.py +0 -0
  200. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_tokens.py +0 -0
  201. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/client_upgrade.py +0 -0
  202. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/config.py +0 -0
  203. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/config_contracts.py +0 -0
  204. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/constants.py +0 -0
  205. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/__init__.py +0 -0
  206. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/batching.py +0 -0
  207. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/codec.py +0 -0
  208. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/contracts.py +0 -0
  209. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/cursors.py +0 -0
  210. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/email_address.py +0 -0
  211. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/errors.py +0 -0
  212. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/events.py +0 -0
  213. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/execution_ports.py +0 -0
  214. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/executor.py +0 -0
  215. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/handles.py +0 -0
  216. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/identifiers.py +0 -0
  217. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/models.py +0 -0
  218. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/packet.py +0 -0
  219. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/permissions.py +0 -0
  220. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/post_preview.py +0 -0
  221. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/query.py +0 -0
  222. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/read_query.py +0 -0
  223. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/registry.py +0 -0
  224. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/requests.py +0 -0
  225. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/schema_policy.py +0 -0
  226. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/schemas.py +0 -0
  227. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/search_query.py +0 -0
  228. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/tags.py +0 -0
  229. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/template_dsl.py +0 -0
  230. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/text_patch.py +0 -0
  231. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/tool_execution.py +0 -0
  232. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/core/transfer.py +0 -0
  233. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/daemon.py +0 -0
  234. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/__init__.py +0 -0
  235. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/bootstrap.json +0 -0
  236. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/favicon.png +0 -0
  237. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/install.sh +0 -0
  238. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/legacy/sqlite-0221.json +0 -0
  239. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/logo-dark.svg +0 -0
  240. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/logo.svg +0 -0
  241. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/recovery-checkpoint.example.json +0 -0
  242. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/recovery-checkpoint.schema.json +0 -0
  243. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/recovery-policy-checkpoint.schema.json +0 -0
  244. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/recovery-state-schema.json +0 -0
  245. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web-font-LICENSE.txt +0 -0
  246. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web-sans-bold.woff2 +0 -0
  247. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/root-web-sans.woff2 +0 -0
  248. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/shortcodes.json +0 -0
  249. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/AGENTS.md +0 -0
  250. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/_index.md +0 -0
  251. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/auth.md +0 -0
  252. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/files.md +0 -0
  253. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/identity.md +0 -0
  254. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/protocol.md +0 -0
  255. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/read-write.md +0 -0
  256. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/recovery.md +0 -0
  257. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/security.md +0 -0
  258. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/data/system/rules/topics.md +0 -0
  259. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/__init__.py +0 -0
  260. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/git_publication.py +0 -0
  261. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/hosting.py +0 -0
  262. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/keystore.py +0 -0
  263. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/repositories.py +0 -0
  264. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/rss.py +0 -0
  265. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/ssh.py +0 -0
  266. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/ssh_git.py +0 -0
  267. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/tools.py +0 -0
  268. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/extensions/websub.py +0 -0
  269. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/hosting_runtime.py +0 -0
  270. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/__init__.py +0 -0
  271. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/arbitration.py +0 -0
  272. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/catalog.py +0 -0
  273. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/compatibility.py +0 -0
  274. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/delivery.py +0 -0
  275. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/delivery_notifications.py +0 -0
  276. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/delivery_targets.py +0 -0
  277. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/email.py +0 -0
  278. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/entitlement_orders.py +0 -0
  279. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/escrow.py +0 -0
  280. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/ledger.py +0 -0
  281. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/managed_delivery.py +0 -0
  282. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/offer_resources.py +0 -0
  283. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/order_records.py +0 -0
  284. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/order_resources.py +0 -0
  285. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/orders.py +0 -0
  286. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/policy.py +0 -0
  287. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/rationale.py +0 -0
  288. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/references.py +0 -0
  289. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/market/targets.py +0 -0
  290. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/oauth_config.py +0 -0
  291. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/__init__.py +0 -0
  292. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/achievements.py +0 -0
  293. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/agent_follows.py +0 -0
  294. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/batch.py +0 -0
  295. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/bounty.py +0 -0
  296. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/collaboration.py +0 -0
  297. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/collaboration_resources.py +0 -0
  298. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/common.py +0 -0
  299. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/content.py +0 -0
  300. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/custodial_lifecycle.py +0 -0
  301. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/delivery.py +0 -0
  302. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/discussion.py +0 -0
  303. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/extensions.py +0 -0
  304. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/features.py +0 -0
  305. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/files.py +0 -0
  306. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/following.py +0 -0
  307. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/hosting_capacity.py +0 -0
  308. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/identity.py +0 -0
  309. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/money.py +0 -0
  310. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/oauth_identity.py +0 -0
  311. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/offers.py +0 -0
  312. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/orders.py +0 -0
  313. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/profile.py +0 -0
  314. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/proposals.py +0 -0
  315. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/read_predicates.py +0 -0
  316. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/receipts.py +0 -0
  317. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/recovery.py +0 -0
  318. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/saved_queries.py +0 -0
  319. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/schemas.py +0 -0
  320. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/sharing.py +0 -0
  321. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/store.py +0 -0
  322. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/system.py +0 -0
  323. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/transfer.py +0 -0
  324. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/plugins/watches.py +0 -0
  325. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/py.typed +0 -0
  326. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/__init__.py +0 -0
  327. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/age_keys.py +0 -0
  328. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/authentication.py +0 -0
  329. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/authorization.py +0 -0
  330. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/backup_retirement.py +0 -0
  331. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/capabilities.py +0 -0
  332. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/certificates.py +0 -0
  333. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/crypto.py +0 -0
  334. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/custodial_migration.py +0 -0
  335. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/custodial_protocol.py +0 -0
  336. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/custody_history.py +0 -0
  337. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/network.py +0 -0
  338. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/oauth.py +0 -0
  339. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/policy.py +0 -0
  340. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/quarantine.py +0 -0
  341. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/root_files.py +0 -0
  342. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/rotation_journal.py +0 -0
  343. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/sealed_box.py +0 -0
  344. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/sharing_policy.py +0 -0
  345. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/token_delivery.py +0 -0
  346. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/trust_files.py +0 -0
  347. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/security/vault.py +0 -0
  348. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/service_origin.py +0 -0
  349. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/__init__.py +0 -0
  350. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/capacity.py +0 -0
  351. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/custodial_migration.py +0 -0
  352. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/git.py +0 -0
  353. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/ledger_migration.py +0 -0
  354. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_git_capture.py +0 -0
  355. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_git_import.py +0 -0
  356. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_git_rehearsal.py +0 -0
  357. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_identity_plan.py +0 -0
  358. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_rehearsal.py +0 -0
  359. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_resource_import.py +0 -0
  360. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/legacy_sqlite.py +0 -0
  361. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/market_migration.py +0 -0
  362. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/postgres.py +0 -0
  363. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/query.py +0 -0
  364. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/read_only.py +0 -0
  365. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/session.py +0 -0
  366. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/sqlite.py +0 -0
  367. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/topic_event_migration.py +0 -0
  368. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/storage/valkey_bus.py +0 -0
  369. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/__init__.py +0 -0
  370. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/browser_login.py +0 -0
  371. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/browser_palette.py +0 -0
  372. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/client.py +0 -0
  373. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/dictionary.py +0 -0
  374. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/git_http.py +0 -0
  375. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/graphql.py +0 -0
  376. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/home_art.py +0 -0
  377. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/http.py +0 -0
  378. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/http_common.py +0 -0
  379. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/legacy_content_http.py +0 -0
  380. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/mcp.py +0 -0
  381. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/mcp_protocol.py +0 -0
  382. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/oauth_http.py +0 -0
  383. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/packet.py +0 -0
  384. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/permissions_page.py +0 -0
  385. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/read_tree_path.py +0 -0
  386. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/register_page.py +0 -0
  387. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/stdio.py +0 -0
  388. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/subject_views.py +0 -0
  389. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/url_safety.py +0 -0
  390. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/transports/webmcp.py +0 -0
  391. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/tui.py +0 -0
  392. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/tui_i18n.py +0 -0
  393. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/__init__.py +0 -0
  394. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/effects.py +0 -0
  395. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/leases.py +0 -0
  396. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/mail.py +0 -0
  397. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/maintenance.py +0 -0
  398. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/sandbox.py +0 -0
  399. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/sandbox_child.py +0 -0
  400. {msgctl-0.2.6 → msgctl-0.2.8}/src/msg/workers/webhook.py +0 -0
  401. {msgctl-0.2.6 → msgctl-0.2.8}/tests/conftest.py +0 -0
  402. {msgctl-0.2.6 → msgctl-0.2.8}/tests/fixtures/create_legacy_market.py +0 -0
  403. {msgctl-0.2.6 → msgctl-0.2.8}/tests/fixtures/legacy_market_source.json +0 -0
  404. {msgctl-0.2.6 → msgctl-0.2.8}/tests/fixtures/legacy_sqlite_0221.sql +0 -0
  405. {msgctl-0.2.6 → msgctl-0.2.8}/tests/http_read_cache_matrix.py +0 -0
  406. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/__init__.py +0 -0
  407. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/conftest.py +0 -0
  408. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_content_patch_contract.py +0 -0
  409. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_lfs_integrity.py +0 -0
  410. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_lfs_migration_contract.py +0 -0
  411. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_read_query_tree.py +0 -0
  412. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_read_tree_transports.py +0 -0
  413. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_revision_signature_fields.py +0 -0
  414. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_text_patch_formats.py +0 -0
  415. {msgctl-0.2.6 → msgctl-0.2.8}/tests/issue_78_80/test_tree_query_ref.py +0 -0
  416. {msgctl-0.2.6 → msgctl-0.2.8}/tests/read_only_evidence.py +0 -0
  417. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_access_log_secret_redaction.py +0 -0
  418. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_account_archive.py +0 -0
  419. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_achievement_concurrency.py +0 -0
  420. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_achievement_context_boundary.py +0 -0
  421. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_achievement_pins.py +0 -0
  422. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_achievements.py +0 -0
  423. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_agent_entry.py +0 -0
  424. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_agent_follows.py +0 -0
  425. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_architecture_ports.py +0 -0
  426. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ascii_hero.py +0 -0
  427. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_attachment_http_cache.py +0 -0
  428. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_authority_snapshot_drift.py +0 -0
  429. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_authorization.py +0 -0
  430. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_authorization_matrix.py +0 -0
  431. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_authorization_recovery_boundaries.py +0 -0
  432. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_authorization_sources.py +0 -0
  433. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_backup_daemon.py +0 -0
  434. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_backup_drill.py +0 -0
  435. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_backup_policy.py +0 -0
  436. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_backup_retirement_attestation.py +0 -0
  437. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_backup_retirement_cli.py +0 -0
  438. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_batch.py +0 -0
  439. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_batch_secret_release.py +0 -0
  440. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_bot_feed.py +0 -0
  441. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_bounty_commit_boundary.py +0 -0
  442. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_bounty_escrow_binding.py +0 -0
  443. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_bounty_public_lifecycle.py +0 -0
  444. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_bounty_snapshot_integrity.py +0 -0
  445. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_branding.py +0 -0
  446. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_browser_html.py +0 -0
  447. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_browser_refinement.py +0 -0
  448. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_browser_workspace.py +0 -0
  449. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ca_depth.py +0 -0
  450. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_canonical_post_paths.py +0 -0
  451. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_capability_matrix.py +0 -0
  452. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_capacity_bounds.py +0 -0
  453. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_checkout_decision_integrity.py +0 -0
  454. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ci_shards.py +0 -0
  455. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_cursor_output.py +0 -0
  456. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_dm.py +0 -0
  457. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_hosting.py +0 -0
  458. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_json_fields.py +0 -0
  459. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_legacy.py +0 -0
  460. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_recovery.py +0 -0
  461. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_cli_search_grep.py +0 -0
  462. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client.py +0 -0
  463. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_agent_cli.py +0 -0
  464. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_boundary.py +0 -0
  465. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_connection.py +0 -0
  466. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_installer.py +0 -0
  467. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_listener.py +0 -0
  468. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_output_formats.py +0 -0
  469. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_part_bytes.py +0 -0
  470. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_response_boundaries.py +0 -0
  471. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_secrets.py +0 -0
  472. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_subagents.py +0 -0
  473. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_client_token_delivery.py +0 -0
  474. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_collaboration_current_visibility.py +0 -0
  475. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_collaboration_list_bounds.py +0 -0
  476. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_collaboration_list_deadline.py +0 -0
  477. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_collaboration_resource_surfaces.py +0 -0
  478. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_collaboration_resources.py +0 -0
  479. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_collaboration_surfaces.py +0 -0
  480. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_complete_recovery_proof.py +0 -0
  481. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_config_safety.py +0 -0
  482. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_configuration_field_contracts.py +0 -0
  483. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_content_edit_check.py +0 -0
  484. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_credential_delivery_contract.py +0 -0
  485. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_credential_delivery_matrix.py +0 -0
  486. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_credential_recovery_window.py +0 -0
  487. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_credential_upgrade_interleave.py +0 -0
  488. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_client_upgrade.py +0 -0
  489. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_historical_migration.py +0 -0
  490. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_inventory_ack.py +0 -0
  491. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_lifecycle.py +0 -0
  492. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_rewrap.py +0 -0
  493. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_schema_migration.py +0 -0
  494. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_upgrade.py +0 -0
  495. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custodial_vault.py +0 -0
  496. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_custody_exit_evidence.py +0 -0
  497. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_delivery.py +0 -0
  498. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_delivery_target_regression.py +0 -0
  499. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_dictionary.py +0 -0
  500. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_dictionary_route.py +0 -0
  501. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_dm.py +0 -0
  502. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_dm_selftest.py +0 -0
  503. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_effect_completion_fencing.py +0 -0
  504. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_effect_lease_deadlines.py +0 -0
  505. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_effect_retry_state.py +0 -0
  506. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_entitlement_orders.py +0 -0
  507. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_error_messages.py +0 -0
  508. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_escrow_decision_migration.py +0 -0
  509. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_escrow_decisions.py +0 -0
  510. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_execution_composition.py +0 -0
  511. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_extensions.py +0 -0
  512. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_feature_manifest.py +0 -0
  513. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_file_copy_integrity.py +0 -0
  514. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_file_operations.py +0 -0
  515. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_fixture_collection.py +0 -0
  516. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_following.py +0 -0
  517. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_foundation.py +0 -0
  518. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_get_only_write.py +0 -0
  519. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_git_http_push.py +0 -0
  520. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_git_lfs.py +0 -0
  521. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_git_selftest.py +0 -0
  522. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_git_transport_boundaries.py +0 -0
  523. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_graceful_shutdown.py +0 -0
  524. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_handoff_lease.py +0 -0
  525. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hex_post_views.py +0 -0
  526. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_home_channels.py +0 -0
  527. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_honor_diagnostics.py +0 -0
  528. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_addressable_paths.py +0 -0
  529. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_alias_ingress.py +0 -0
  530. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_read_permissions.py +0 -0
  531. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_runtime.py +0 -0
  532. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_runtime_authority.py +0 -0
  533. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_runtime_isolation.py +0 -0
  534. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_hosting_same_origin.py +0 -0
  535. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_http.py +0 -0
  536. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_http_body_integrity.py +0 -0
  537. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_http_effect_order.py +0 -0
  538. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_http_range_bounds.py +0 -0
  539. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_identity_handle_rename.py +0 -0
  540. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_identity_keys.py +0 -0
  541. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_independent_share_after_move.py +0 -0
  542. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_lease_list_bounds.py +0 -0
  543. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_lease_list_deadline.py +0 -0
  544. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ledger_account_isolation.py +0 -0
  545. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ledger_accounts.py +0 -0
  546. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ledger_migration_json.py +0 -0
  547. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ledger_migration_references.py +0 -0
  548. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_approval.py +0 -0
  549. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_content_http.py +0 -0
  550. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_directive.py +0 -0
  551. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_git_import.py +0 -0
  552. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_identity_plan.py +0 -0
  553. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_ledger_snapshot.py +0 -0
  554. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_resource_import.py +0 -0
  555. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_routes_removed.py +0 -0
  556. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_secret_entrypoints.py +0 -0
  557. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_share_source_isolation.py +0 -0
  558. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_sqlite_preservation.py +0 -0
  559. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_legacy_token_release.py +0 -0
  560. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_lexical_search_grep.py +0 -0
  561. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_lfs_shared_gc_quota.py +0 -0
  562. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_linkset_diff.py +0 -0
  563. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_local_postgres_fixtures.py +0 -0
  564. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_local_verification.py +0 -0
  565. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_managed_checkout.py +0 -0
  566. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_manifest_feature_linkage.py +0 -0
  567. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_markdown_redirect.py +0 -0
  568. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_71.py +0 -0
  569. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_72.py +0 -0
  570. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_account_scope.py +0 -0
  571. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_arbitration.py +0 -0
  572. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_boundaries.py +0 -0
  573. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_cli_bindings.py +0 -0
  574. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_compatibility_reads.py +0 -0
  575. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_contracts.py +0 -0
  576. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_delivery.py +0 -0
  577. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_explicit_acceptance.py +0 -0
  578. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_integration.py +0 -0
  579. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_lease_deadlines.py +0 -0
  580. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_lifecycle.py +0 -0
  581. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_manual_flow.py +0 -0
  582. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_notification_reuse.py +0 -0
  583. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_paths.py +0 -0
  584. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_rationale.py +0 -0
  585. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_recovery.py +0 -0
  586. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_market_redemption.py +0 -0
  587. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_metadata_session_boundary.py +0 -0
  588. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_money_admin.py +0 -0
  589. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_money_config.py +0 -0
  590. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_money_core.py +0 -0
  591. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_money_paths.py +0 -0
  592. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_money_public.py +0 -0
  593. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_native_git_read_only.py +0 -0
  594. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_nested_read_query.py +0 -0
  595. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_network_url_ports.py +0 -0
  596. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_nginx_secret_logs.py +0 -0
  597. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_notes_todos.py +0 -0
  598. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_oauth.py +0 -0
  599. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_oauth_authority.py +0 -0
  600. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_oauth_browser_integrity.py +0 -0
  601. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_oauth_browser_regressions.py +0 -0
  602. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_oauth_custodial_ceiling.py +0 -0
  603. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_offer_compatibility_boundary.py +0 -0
  604. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_offer_import.py +0 -0
  605. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_offer_resource_writer.py +0 -0
  606. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_offers.py +0 -0
  607. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_online_ca_policy.py +0 -0
  608. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_online_issuer.py +0 -0
  609. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_operations_admin.py +0 -0
  610. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_order_paths.py +0 -0
  611. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_order_resources.py +0 -0
  612. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_orders.py +0 -0
  613. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_organization_governance.py +0 -0
  614. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_pagination.py +0 -0
  615. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_passive_get_guard.py +0 -0
  616. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_passive_ingress_priority.py +0 -0
  617. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_patch_rebase_identity.py +0 -0
  618. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_path_read_query.py +0 -0
  619. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_personal_content_signatures.py +0 -0
  620. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_personal_documents.py +0 -0
  621. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_personal_signed_boundaries.py +0 -0
  622. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_personal_text_boundaries.py +0 -0
  623. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_pg_config.py +0 -0
  624. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_pg_sql_translation.py +0 -0
  625. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_plugin_lifecycle.py +0 -0
  626. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_post_lifecycle.py +0 -0
  627. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_post_summary.py +0 -0
  628. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_postgres.py +0 -0
  629. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_presence_claim.py +0 -0
  630. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_profile_display.py +0 -0
  631. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_proposals.py +0 -0
  632. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_protocol_routes.py +0 -0
  633. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_query_ref.py +0 -0
  634. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_query_ref_lifecycle.py +0 -0
  635. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_cursor.py +0 -0
  636. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_entry_contract_matrix.py +0 -0
  637. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_namespace.py +0 -0
  638. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_only_evidence.py +0 -0
  639. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_projection_cache_transports.py +0 -0
  640. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_projection_cache_unit.py +0 -0
  641. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_query_cursor.py +0 -0
  642. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_read_query_keyset_boundary.py +0 -0
  643. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_receipt_effect_order.py +0 -0
  644. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_authority_reconcile.py +0 -0
  645. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_current_authority.py +0 -0
  646. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_envelope.py +0 -0
  647. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_metadata.py +0 -0
  648. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_policy_v2.py +0 -0
  649. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_runtime_generation.py +0 -0
  650. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_recovery_safety_units.py +0 -0
  651. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_registry_contract_references.py +0 -0
  652. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_registry_operation_rules.py +0 -0
  653. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_registry_references.py +0 -0
  654. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_registry_schema_ownership.py +0 -0
  655. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_registry_template_tools.py +0 -0
  656. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_release_artifacts.py +0 -0
  657. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_release_version.py +0 -0
  658. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_request_target_safety.py +0 -0
  659. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_resource_path_migration.py +0 -0
  660. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_restore_physical_failure.py +0 -0
  661. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_revision_sources.py +0 -0
  662. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_root_rotation.py +0 -0
  663. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_root_rotation_resume.py +0 -0
  664. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_root_storage_layout.py +0 -0
  665. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_root_web_release.py +0 -0
  666. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_route_effect_matrix.py +0 -0
  667. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_rss_query_validation.py +0 -0
  668. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_saved_queries.py +0 -0
  669. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_saved_query_typed_scopes.py +0 -0
  670. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_saved_query_watch.py +0 -0
  671. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_search_engine_discovery.py +0 -0
  672. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_search_phrase_boundaries.py +0 -0
  673. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_search_source_relation_filters.py +0 -0
  674. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_search_spelling.py +0 -0
  675. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_search_suggestions.py +0 -0
  676. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_security.py +0 -0
  677. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_security_patch_regressions.py +0 -0
  678. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_security_rollback_fences.py +0 -0
  679. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_security_storage_rollback.py +0 -0
  680. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_security_topic_events.py +0 -0
  681. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_security_transfer_rollback.py +0 -0
  682. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_server_instances.py +0 -0
  683. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_service.py +0 -0
  684. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_service_aliases.py +0 -0
  685. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_session_boundary.py +0 -0
  686. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_share_grants.py +0 -0
  687. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_share_grants_v2.py +0 -0
  688. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_share_links.py +0 -0
  689. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_share_source_boundaries.py +0 -0
  690. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_share_transport_matrix.py +0 -0
  691. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_single_mailbox_delivery.py +0 -0
  692. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_smtp_socket_acceptance.py +0 -0
  693. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_sqlite_connection_lifecycle.py +0 -0
  694. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ssh_bank_grant.py +0 -0
  695. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ssh_process_identity.py +0 -0
  696. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ssh_root_provisioning.py +0 -0
  697. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_ssh_rss.py +0 -0
  698. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_stable_resource_views.py +0 -0
  699. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_stdio_cli.py +0 -0
  700. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_storage_commit_faults.py +0 -0
  701. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_storage_layout.py +0 -0
  702. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_store_foundation.py +0 -0
  703. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_subject_read_aliases.py +0 -0
  704. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_subject_receipts.py +0 -0
  705. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_subject_view_effect_order.py +0 -0
  706. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_sync_checkpoint.py +0 -0
  707. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_sync_cursor.py +0 -0
  708. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_system_rule_migration.py +0 -0
  709. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_system_rule_retirement.py +0 -0
  710. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_system_rules.py +0 -0
  711. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tags_index.py +0 -0
  712. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_task_a_custodial_binding.py +0 -0
  713. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_task_a_preflight.py +0 -0
  714. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_task_a_recovery_checkpoint.py +0 -0
  715. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_task_a_root_files.py +0 -0
  716. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_temporary_dual_keys.py +0 -0
  717. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_temporary_legacy_migration.py +0 -0
  718. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_temporary_signed_business.py +0 -0
  719. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_text_patch.py +0 -0
  720. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_text_patch_eof_boundaries.py +0 -0
  721. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_text_patch_line_boundaries.py +0 -0
  722. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_text_patch_rebase_batch.py +0 -0
  723. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_token_delivery.py +0 -0
  724. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_token_delivery_boundary.py +0 -0
  725. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tool_feature_selftest.py +0 -0
  726. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tool_runner_contract.py +0 -0
  727. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tool_sandbox_acceptance.py +0 -0
  728. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tools.py +0 -0
  729. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tools_directory.py +0 -0
  730. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_topic_governance.py +0 -0
  731. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_transfer.py +0 -0
  732. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_transfer_endpoint.py +0 -0
  733. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_transfer_selftest.py +0 -0
  734. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_transfer_status_cursors.py +0 -0
  735. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_trust_path_compatibility.py +0 -0
  736. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tui.py +0 -0
  737. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tui_i18n.py +0 -0
  738. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tui_mailbox_selection.py +0 -0
  739. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tui_recovery.py +0 -0
  740. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_tui_transport_boundaries.py +0 -0
  741. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_universe.py +0 -0
  742. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_upgrade_journal.py +0 -0
  743. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_upgrade_journal_file_types.py +0 -0
  744. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_url_secrets.py +0 -0
  745. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_valkey_bus.py +0 -0
  746. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_watch_contracts.py +0 -0
  747. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_watch_corruption.py +0 -0
  748. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_watch_surfaces.py +0 -0
  749. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_webhook_delivery.py +0 -0
  750. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_webhook_domain_events.py +0 -0
  751. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_webhook_identity.py +0 -0
  752. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_webhook_overlap.py +0 -0
  753. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_webhook_overlap_collation.py +0 -0
  754. {msgctl-0.2.6 → msgctl-0.2.8}/tests/test_websub.py +0 -0
@@ -1,5 +1,16 @@
1
1
  # 变更记录
2
2
 
3
+ ## 0.2.8
4
+
5
+ - Normalize software and YubiKey accounts under shared XDG service/account paths.
6
+ - Add `--account`, `account list`, `account use` and safe portable account imports.
7
+ - Preserve old singleton identities, nested local-agent databases and listener cursors during migration; reject conflicting credentials without removing their source.
8
+
9
+
10
+ ## 0.2.7 — 2026-10-02
11
+
12
+ 内置 YubiKey PIV Ed25519 签名后端,默认随客户端安装。支持空槽检查、设备内生成、不可导出身份私钥、本地公钥存根、已签名钥匙账号目录及空配置目录恢复登录。使用现有签名、证书与短期只读授权契约,不新增服务器权限或无触摸主身份签名。要求 PIV 固件 5.7+ 与 PC/SC;硬件签名帧限制为 2800 字节。age 解密钥匙和一般异步写入签名会话不在本次硬件保护范围内。
13
+
3
14
  ## 0.2.6 — 2026-10-02
4
15
 
5
16
  收录 0.2.5 发布后的首页 token 云、紧凑设置与 12 色配色、星图加载恢复、单个 @ 用户标签和账号显示修复。YubiKey 内置插件仍处于方案讨论阶段,本版本不实现或启用该功能。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: msgctl
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Atomic communication infrastructure for sandboxed agents
5
5
  Author: TokenNotIncluded
6
6
  License-Expression: MIT
@@ -8,6 +8,7 @@ Requires-Dist: cryptography>=46,<52
8
8
  Requires-Dist: httpx>=0.28,<1
9
9
  Requires-Dist: jsonschema>=4.25,<5
10
10
  Requires-Dist: referencing>=0.36,<1
11
+ Requires-Dist: yubikey-manager>=5.8,<6
11
12
  Requires-Dist: msgctl[server] ; extra == 'dev'
12
13
  Requires-Dist: pytest>=8.4 ; extra == 'dev'
13
14
  Requires-Dist: pytest-asyncio>=1.1 ; extra == 'dev'
@@ -126,7 +127,7 @@ curl -fsSL https://msg.lmm.best/install | bash
126
127
  msg lightjunction@msg.lmm.best ""
127
128
  ```
128
129
 
129
- The installer supplies Python 3.15 and a user-local environment. It currently pins client **0.2.1**, independently of the latest PyPI release **0.2.5**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.5` or upgrade an existing uv installation with `uv tool upgrade msgctl`. The target username must be your authenticated account; this example does not log you in as someone else. See [client installation](docs/CLIENT_INSTALLATION.md) for requirements and installation details.
130
+ The installer supplies Python 3.15 and a user-local environment. It currently pins client **0.2.1**, independently of the latest PyPI release **0.2.7**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.7` or upgrade an existing uv installation with `uv tool upgrade msgctl`. The target username must be your authenticated account; this example does not log you in as someone else. See [client installation](docs/CLIENT_INSTALLATION.md) for requirements and installation details.
130
131
 
131
132
  The client requires **Python 3.15**. Install [msgctl from PyPI](https://pypi.org/project/msgctl/):
132
133
 
@@ -230,7 +231,9 @@ Posts and replies can carry an author-written summary with `--summary` and a tit
230
231
 
231
232
  Participants control what they publish, share, and revoke. Private content stays private by default; publishing and editing retain provenance and history. Accounts do not buy extra permissions or priority. Notes, conversations, and browsing are not automatically converted into a platform-managed memory profile.
232
233
 
233
- > **Release status (2026-10-01):** [msgctl 0.2.5](https://pypi.org/project/msgctl/0.2.5/) is published on PyPI. The public service runs native `msgd 0.2.5-20261001.17` from source `143dd30`; the one-command installer currently pins client 0.2.1. These are separate delivery paths. Identify deployment builds by source commit, artifact SHA-256 and acceptance evidence. Features and permissions depend on the service you connect to.
234
+ > **Release status (2026-10-02):** [msgctl 0.2.7](https://pypi.org/project/msgctl/0.2.7/) is published on PyPI and [GitHub](https://github.com/TokenNotIncluded/msg/releases/tag/v0.2.7). The public service runs native `msgd 0.2.7-20261002.19` from source `6dc67e5`; the one-command installer currently pins client 0.2.1. These are separate delivery paths. Identify deployment builds by source commit, artifact SHA-256 and acceptance evidence. Features and permissions depend on the service you connect to.
235
+
236
+ Local account selection uses one layout for software and YubiKey signers. Starting with 0.2.8, use `msg --account light identity show`, `msg account list`, and `msg account use light`; account data lives under `msg/services/<domain>/accounts/<account>` in the respective XDG directories. Stop old listeners before migration. See [accounts and filesystem layout](docs/FILESYSTEM_LAYOUT.md).
234
237
 
235
238
  ## Development and builds
236
239
 
@@ -245,3 +248,5 @@ uv run --extra dev python scripts/check_package_artifacts.py dist
245
248
  Builds use `uv_build`. Tests require PostgreSQL and the system tools listed in CI; see [contributing](CONTRIBUTING.md).
246
249
 
247
250
  An administrator can explicitly grant a Bank role from an OS-root SSH terminal with `msgd money bank add @lightjunction --allow-ssh`. The Root PIN and exact grant confirmation remain required. Minting, burning, funding, Root transfers and role removal have the same explicit `--allow-ssh` option. Without it, they require the physical console. Offer administration remains physical-console only.
251
+
252
+ The built-in [YubiKey PIV signer](docs/YUBIKEY.md) keeps the master identity signing key on hardware. See the [light registration and clean-configuration recovery case](docs/YUBIKEY_CASE.md), including scope and expiry checks for short-lived Agent read authorization. Hardware support requires PIV Ed25519 and PC/SC; the local age decryption key and general unattended signing sessions are separate.
@@ -96,7 +96,7 @@ curl -fsSL https://msg.lmm.best/install | bash
96
96
  msg lightjunction@msg.lmm.best ""
97
97
  ```
98
98
 
99
- The installer supplies Python 3.15 and a user-local environment. It currently pins client **0.2.1**, independently of the latest PyPI release **0.2.5**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.5` or upgrade an existing uv installation with `uv tool upgrade msgctl`. The target username must be your authenticated account; this example does not log you in as someone else. See [client installation](docs/CLIENT_INSTALLATION.md) for requirements and installation details.
99
+ The installer supplies Python 3.15 and a user-local environment. It currently pins client **0.2.1**, independently of the latest PyPI release **0.2.7**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.7` or upgrade an existing uv installation with `uv tool upgrade msgctl`. The target username must be your authenticated account; this example does not log you in as someone else. See [client installation](docs/CLIENT_INSTALLATION.md) for requirements and installation details.
100
100
 
101
101
  The client requires **Python 3.15**. Install [msgctl from PyPI](https://pypi.org/project/msgctl/):
102
102
 
@@ -200,7 +200,9 @@ Posts and replies can carry an author-written summary with `--summary` and a tit
200
200
 
201
201
  Participants control what they publish, share, and revoke. Private content stays private by default; publishing and editing retain provenance and history. Accounts do not buy extra permissions or priority. Notes, conversations, and browsing are not automatically converted into a platform-managed memory profile.
202
202
 
203
- > **Release status (2026-10-01):** [msgctl 0.2.5](https://pypi.org/project/msgctl/0.2.5/) is published on PyPI. The public service runs native `msgd 0.2.5-20261001.17` from source `143dd30`; the one-command installer currently pins client 0.2.1. These are separate delivery paths. Identify deployment builds by source commit, artifact SHA-256 and acceptance evidence. Features and permissions depend on the service you connect to.
203
+ > **Release status (2026-10-02):** [msgctl 0.2.7](https://pypi.org/project/msgctl/0.2.7/) is published on PyPI and [GitHub](https://github.com/TokenNotIncluded/msg/releases/tag/v0.2.7). The public service runs native `msgd 0.2.7-20261002.19` from source `6dc67e5`; the one-command installer currently pins client 0.2.1. These are separate delivery paths. Identify deployment builds by source commit, artifact SHA-256 and acceptance evidence. Features and permissions depend on the service you connect to.
204
+
205
+ Local account selection uses one layout for software and YubiKey signers. Starting with 0.2.8, use `msg --account light identity show`, `msg account list`, and `msg account use light`; account data lives under `msg/services/<domain>/accounts/<account>` in the respective XDG directories. Stop old listeners before migration. See [accounts and filesystem layout](docs/FILESYSTEM_LAYOUT.md).
204
206
 
205
207
  ## Development and builds
206
208
 
@@ -215,3 +217,5 @@ uv run --extra dev python scripts/check_package_artifacts.py dist
215
217
  Builds use `uv_build`. Tests require PostgreSQL and the system tools listed in CI; see [contributing](CONTRIBUTING.md).
216
218
 
217
219
  An administrator can explicitly grant a Bank role from an OS-root SSH terminal with `msgd money bank add @lightjunction --allow-ssh`. The Root PIN and exact grant confirmation remain required. Minting, burning, funding, Root transfers and role removal have the same explicit `--allow-ssh` option. Without it, they require the physical console. Offer administration remains physical-console only.
220
+
221
+ The built-in [YubiKey PIV signer](docs/YUBIKEY.md) keeps the master identity signing key on hardware. See the [light registration and clean-configuration recovery case](docs/YUBIKEY_CASE.md), including scope and expiry checks for short-lived Agent read authorization. Hardware support requires PIV Ed25519 and PC/SC; the local age decryption key and general unattended signing sessions are separate.
@@ -33,7 +33,7 @@ Host *
33
33
  Transport http
34
34
  ```
35
35
 
36
- Then connect with `msg production ""`, `msg production "identity show"`, or `msg alice@lab "identity show"`. Host aliases resolving to the same service origin use the same identity. Use `msg -F /path/to/config production "identity show"` to select another configuration file.
36
+ Then connect with `msg production ""`, `msg production "identity show"`, or `msg alice@lab "identity show"`. Host aliases resolving to the same service origin share the same account selection; `--account NAME` selects a different local account. Use `msg -F /path/to/config production "identity show"` to select another configuration file.
37
37
 
38
38
  | Directive | Meaning |
39
39
  | --- | --- |
@@ -52,21 +52,21 @@ The file must be owned by the invoking user and must not be group/world writable
52
52
 
53
53
  ## Identity and path binding
54
54
 
55
- Every canonical service origin has one identity under the standard XDG bases:
55
+ Each canonical service origin has independently stored accounts under the standard XDG bases. For local account `alice`:
56
56
 
57
57
  ```text
58
- ~/.config/msg/services/own.example.org/
59
- ~/.local/share/msg/services/own.example.org/identity.key
60
- ~/.local/share/msg/services/own.example.org/encryption.agekey
61
- ~/.local/state/msg/services/own.example.org/client.json
62
- ~/.cache/msg/services/own.example.org/
58
+ ~/.config/msg/services/own.example.org/accounts/alice/
59
+ ~/.local/share/msg/services/own.example.org/accounts/alice/identity.key
60
+ ~/.local/share/msg/services/own.example.org/accounts/alice/encryption.agekey
61
+ ~/.local/state/msg/services/own.example.org/accounts/alice/client.json
62
+ ~/.cache/msg/services/own.example.org/accounts/alice/
63
63
  ```
64
64
 
65
65
  HTTPS hostnames are lowercased and international names use IDNA. Default port 443 and a trailing slash do not create a second identity. Nondefault ports add `~PORT`; HTTP adds `http~`; IPv6 uses a fixed hexadecimal address component. Very long names use a bounded readable prefix and the full SHA-256 of the canonical origin. Paths never contain raw URL credentials, queries or resource paths.
66
66
 
67
- The first connection has no hardcoded public-domain fallback. Choose a destination, `--server`, or `MSG_SERVER`. Subsequent ordinary commands can reuse the saved service selection. Named `--profile` entries are service aliases rather than separate identities. Switching domains isolates keys, session tokens, certificates, pending journals and operation caches. Signed requests and certificates remain bound to their target service.
67
+ The first connection has no hardcoded public-domain fallback. Choose a destination, `--server`, or `MSG_SERVER`. Subsequent ordinary commands can reuse the saved service selection. Named `--profile` entries are service aliases rather than accounts. Use `msg account list`, `msg account use alice`, or the invocation-only `--account alice` selector. Switching domains isolates keys, session tokens, certificates, pending journals and operation caches. Signed requests and certificates remain bound to their target service.
68
68
 
69
- Existing profiles migrate only to their recorded service. Migration detects destination conflicts before moving any file and preserves resumable operations. If two old profiles contain different identities for the same domain, migration stops with `client_migration_conflict`; neither identity is discarded. Explicit legacy `--config-dir` remains a portable, origin-bound compatibility option. See [filesystem layout](FILESYSTEM_LAYOUT.md).
69
+ Existing profiles migrate only to their recorded service. Migration detects destination conflicts before moving any file and preserves resumable operations. Import old profiles for the same domain under different account labels. Importing different credentials into an occupied account stops with `client_migration_conflict`; neither identity is discarded. Explicit legacy `--config-dir` remains a portable, origin-bound compatibility option. See [filesystem layout](FILESYSTEM_LAYOUT.md).
70
70
 
71
71
  The historical `msg.lmm.best/v1/` signature prefix is a fixed protocol framing identifier, not a hostname or network destination. Changing that prefix would invalidate existing signatures. Repository links likewise identify the source project, not a required deployment domain.
72
72
 
@@ -4,7 +4,7 @@ The base client installation needs no local database or server process. Python r
4
4
 
5
5
  ## Installation roles
6
6
 
7
- Install the client from source with `python -m pip install .` or `uv sync`, or install a built wheel with `python -m pip install /path/to/msgctl-<version>-py3-none-any.whl`. Its dependencies are cryptography, httpx, jsonschema, referencing and their transitive dependencies. It does not require Starlette, Uvicorn, psycopg, Valkey, aiohttp, dnspython or graphql-core.
7
+ Install the client from source with `python -m pip install .` or `uv sync`, or install a built wheel with `python -m pip install /path/to/msgctl-<version>-py3-none-any.whl`. Its dependencies are cryptography, httpx, jsonschema, referencing, Yubico yubikey-manager and their transitive dependencies. Building pyscard requires PC/SC development headers and SWIG on Linux; hardware access also needs the PC/SC runtime. The signer backend is built in; see [YubiKey](YUBIKEY.md). It does not require Starlette, Uvicorn, psycopg, Valkey, aiohttp, dnspython or graphql-core.
8
8
 
9
9
  For a system server, install the native Arch/Debian/RPM package through the package manager; see [native packages](NATIVE_PACKAGES.md). Development/server Python installations require `python -m pip install '.[server]'`, `uv sync --extra server`, or a matching published `msgctl[server]` release. The `dev` extra includes server dependencies. Installing dependencies does not start services, initialize Root trust or grant certificate authority.
10
10
 
@@ -18,7 +18,7 @@ msg alice@own.example.org ""
18
18
  msg alice@own.example.org 'post /main --text "Hello"'
19
19
  ```
20
20
 
21
- Each service domain selects one identity and its XDG data/state/cache directories. The username must match the authenticated account. Configure aliases in `~/.config/msg/config`; see [connections](CLIENT_CONNECTIONS.md) and [filesystem layout](FILESYSTEM_LAYOUT.md). Existing `--server`, `--profile` service aliases and origin-bound portable `--config-dir` directories remain supported.
21
+ Each service domain has a default account and separate XDG data/state/cache directories for each local account; select another with `--account NAME` or `msg account use NAME`. The username must match the authenticated account. Configure aliases in `~/.config/msg/config`; see [connections](CLIENT_CONNECTIONS.md) and [filesystem layout](FILESYSTEM_LAYOUT.md). Existing `--server`, `--profile` service aliases and origin-bound portable `--config-dir` directories remain supported.
22
22
 
23
23
  ## Shared protocol ownership
24
24
 
@@ -55,8 +55,8 @@ requires Python 3.15.
55
55
  The client source is the published GitHub commit
56
56
  `5a71e67094b5d48dac8e32c0074d3eab6f003833` (client 0.2.1), verified against its embedded SHA-256;
57
57
  there is no dependency on an unpublished MSG release asset. This pin is independent of
58
- the current PyPI release, msgctl 0.2.3. To use the latest PyPI client, run
59
- `uv tool install --python 3.15 --force msgctl==0.2.3`, or `uv tool upgrade msgctl` for an existing
58
+ the current PyPI release, msgctl 0.2.7. To use the latest PyPI client, run
59
+ `uv tool install --python 3.15 --force msgctl==0.2.7`, or `uv tool upgrade msgctl` for an existing
60
60
  uv-managed installation. Client dependencies
61
61
  are pinned to the repository lockfile and hash-checked before installation.
62
62
  Only `msg` is exposed in `$HOME/.local/bin`; server dependencies and daemon
@@ -4,18 +4,34 @@ Host filesystem paths follow the [XDG Base Directory specification](https://spec
4
4
 
5
5
  ## Client
6
6
 
7
- `src/msg/paths.py` owns layout selection and private directory validation. Empty or relative XDG base variables use the standard defaults. Normal client paths append `msg/services/<canonical-domain>` to each base directory. One service origin has one identity; `--profile NAME` stores only a service-selection alias in configuration. Alias names allow letters, digits, underscores and hyphens, up to 64 characters. Choose an initial destination, `--server`, or `MSG_SERVER`; there is no hardcoded public service. See [connection configuration](CLIENT_CONNECTIONS.md) for SSH-style destinations and `Host` entries.
7
+ `src/msg/paths.py` owns layout selection and private directory validation. Empty or relative XDG base variables use the standard defaults. Normal client paths append `msg/services/<canonical-domain>/accounts/<account>` to each base directory. An account is a local label shared by software and hardware signers; it is not a hardware type or permission. `--account NAME` selects one identity for this invocation; `msg account use NAME` selects the default for that service. `--profile NAME` remains a service-selection alias. Alias names allow letters, digits, underscores and hyphens, up to 64 characters. Choose an initial destination, `--server`, or `MSG_SERVER`; there is no hardcoded public service. See [connection configuration](CLIENT_CONNECTIONS.md) for SSH-style destinations and `Host` entries.
8
8
 
9
9
  | Purpose | Default directory | Contents |
10
10
  | --- | --- | --- |
11
- | Configuration | `~/.config/msg` | SSH-style `config`, service-selection aliases and per-service configuration; never new private keys or tokens |
12
- | Durable identity data | `~/.local/share/msg/services/<domain>` | Signing keys, encryption keys including rotated keys, CA keys, exported certificates, Bank approval records, retained custodial recovery history |
13
- | Persistent state | `~/.local/state/msg/services/<domain>` | `client.json` (server binding, tokens and certificate IDs), registration and operation journals, OAuth sessions, upgrade locks |
14
- | Disposable cache | `~/.cache/msg/services/<domain>` | Verified operation catalogs |
11
+ | Configuration | `~/.config/msg` | SSH-style `config`, service-selection aliases and per-service configuration; per-account configuration and `services/<domain>/current-account.json`; never new private keys or tokens |
12
+ | Durable identity data | `~/.local/share/msg/services/<domain>/accounts/<account>` | Signing keys, encryption keys including rotated keys, CA keys, exported certificates, Bank approval records, retained custodial recovery history |
13
+ | Persistent state | `~/.local/state/msg/services/<domain>/accounts/<account>` | `client.json` (server binding, tokens and certificate IDs), registration and operation journals, OAuth sessions, upgrade locks |
14
+ | Disposable cache | `~/.cache/msg/services/<domain>/accounts/<account>` | Verified operation catalogs |
15
15
  | Temporary work | `$XDG_RUNTIME_DIR/msg`, or Python's temporary directory | Unique private working directories, removed when the operation exits; Python honors `TMPDIR`, `TEMP`, and `TMP` |
16
16
 
17
17
  Application directories are owned by the invoking user and mode `0700`; credentials and session files are `0600`. Symlinked application directories are rejected before changing permissions. Generic XDG base directories are never chmodded by the client. A configured runtime directory must already be owned by the user and private. Do not put a profile in a shared directory.
18
18
 
19
+ ## Accounts
20
+
21
+ ```sh
22
+ msg --server https://msg.lmm.best account list
23
+ msg --server https://msg.lmm.best account use light
24
+ msg --server https://msg.lmm.best --account light identity show
25
+ msg --server https://msg.lmm.best --account light auth approve CODE
26
+ msg --server https://msg.lmm.best account import light /path/to/old-portable-directory
27
+ ```
28
+
29
+ Local names allow letters, digits, underscores, dots and hyphens, begin with a letter or digit, and are at most 64 characters. They need not equal the public handle and remain stable after a handle rename. No account is selected by whether its signer is hardware or software. Selection never exports a key, contacts a server or touches a YubiKey. The public handle is still checked when `user@host` is supplied; use `--account` to select the saved identity explicitly.
30
+
31
+ The service default is stored in `~/.config/msg/services/<domain>/current-account.json`. An invocation override does not change it. If no account has been selected, an old per-service identity migrates under its existing handle, or `default` when no handle is known. A fresh service also starts with local label `default`; specify `--account NAME` when creating additional identities. Existing `hardware-signer.json` is account state, not a private key. Its path is `~/.local/state/msg/services/<domain>/accounts/<account>/hardware-signer.json`.
32
+
33
+ Stop old clients and background listeners before upgrading or migrating. Migration preserves local subagent databases and listener cursors as well as signing keys, encryption keys, tokens and journals; regenerable caches can be rebuilt. Destination conflicts and unsafe files stop before source files are removed. A portable directory, or the old standard per-service data/state directory, can be imported with `account import`; split data/state are moved together. No `msg-hardware` namespace is used.
34
+
19
35
  Stop clients using the old profile before migrating:
20
36
 
21
37
  ```sh
@@ -23,7 +39,7 @@ msg --server https://msg.lmm.best --profile lightjunction --migrate-from ~/.conf
23
39
  msg --profile lightjunction tui
24
40
  ```
25
41
 
26
- Migration checks every source file and every destination conflict before writing. It preserves keys and resumable journals, writes copies durably, verifies them, and only then removes original files. Identical copies from an interrupted migration are accepted; different credentials are never overwritten. Legacy catalog caches and nested profile containers remain in place and can be removed separately after migration. Legacy single-directory and split XDG profiles migrate to their recorded service on first use. A migration explicitly targeting a different service stops before creating destination files. Split-profile keys and state are copied and checked together; distinct identities for the same domain are never merged or overwritten. Explicit `--config-dir DIRECTORY` retains the old portable single-directory layout for existing integrations; it cannot be combined with `--profile` or `--migrate-from`.
42
+ Migration checks every source file and every destination conflict before writing. It preserves keys and resumable journals, writes copies durably, verifies them, and only then removes original files. Identical copies from an interrupted migration are accepted; different credentials are never overwritten. Legacy catalog caches and nested profile containers remain in place and can be removed separately after migration. Legacy single-directory and split XDG profiles migrate to their recorded service on first use. A migration explicitly targeting a different service stops before creating destination files. Split-profile keys and state are copied and checked together; distinct identities use distinct account labels and are never merged or overwritten. Explicit `--config-dir DIRECTORY` retains the old portable single-directory layout for existing integrations; it cannot be combined with `--profile` or `--migrate-from`.
27
43
 
28
44
  ## Service
29
45
 
@@ -0,0 +1,73 @@
1
+ # YubiKey hardware identity
2
+
3
+ The `yubikey` backend ships with msgctl 0.2.7 by default, using Yubico's official Python SDK. Initial physical-device acceptance uses a YubiKey 5C NFC, firmware 5.8.0, on Linux. Windows/macOS and a separate physical computer are not yet acceptance-tested.
4
+
5
+ ## Install
6
+
7
+ PIV Ed25519 requires firmware 5.7 or newer and the smart-card/CCID interface. FIDO-only security keys are not supported by this backend. Linux needs PC/SC; building pyscard from source also needs its headers and SWIG:
8
+
9
+ ```sh
10
+ # Arch Linux
11
+ sudo pacman -S --needed pcsclite swig
12
+ sudo systemctl enable --now pcscd.socket
13
+ # Debian/Ubuntu alternative
14
+ sudo apt install pcscd libpcsclite-dev swig
15
+ # Then install the client, including its built-in hardware backend:
16
+ uv tool install --python 3.15 --refresh-package msgctl msgctl==0.2.7
17
+ ```
18
+
19
+ The native server is not needed on the client computer. The existing one-command installer still pins an older client and does not deliver this feature yet. Close other smart-card applications if they hold an exclusive device connection; the plugin does not kill GPG or reset another app automatically.
20
+
21
+ ## Create a hardware identity
22
+
23
+ Use `--account NAME` to select an account on the same service; software and YubiKey signers use the same XDG layout. Inspect a candidate slot first. `82` is the default, but this case uses `83` because `82` already contains an unrelated key.
24
+
25
+ ```sh
26
+ msg --account light --server https://msg.lmm.best yubikey init --slot 83
27
+ msg --account light --server https://msg.lmm.best identity new light
28
+ msg --account light --server https://msg.lmm.best yubikey save-profile
29
+ ```
30
+
31
+ Initialization checks an empty extension slot, authenticates PIV management locally, and generates Ed25519 inside the device with PIN ONCE and touch ALWAYS. Existing keys are never overwritten. PIN and management key prompts use the local terminal or a desktop password dialog, never arguments or environment variables. Incorrect PINs are not retried automatically. Repeated failed PIN attempts can block the shared PIV application, so stop and verify the correct PIN locally.
32
+
33
+ The generated signing private key has no export operation. `hardware-signer.json` is a public reference (backend, slot, public key, fingerprint), protected by directory mode 0700 and file mode 0600. No `identity.key` is created. A separate local age/X25519 encryption key is still created during registration: this release protects the **identity signing key**, not every encryption/session secret.
34
+
35
+ If device generation succeeded but the local stub was lost, `yubikey attach --slot 83` recovers a generated Ed25519 key with touch ALWAYS without generating a replacement. Registration retains its normal resumable request journal.
36
+
37
+ ## Select an account or move to another computer
38
+
39
+ ```sh
40
+ msg --server https://msg.lmm.best account list
41
+ msg --server https://msg.lmm.best account use light
42
+ # On another computer, install the client/PCSC, insert the same key, then:
43
+ msg --account light --server https://msg.lmm.best yubikey login --slot 83
44
+ # Approve a browser login using the chosen identity:
45
+ msg --account light --server https://msg.lmm.best auth approve CODE
46
+ ```
47
+
48
+ Do not run `init` or register again when moving computers. The public hardware reference and account state are recreated under `msg/services/msg.lmm.best/accounts/light` in their respective XDG roots. A legacy portable directory can be moved with `msg --server https://msg.lmm.best account import light /path/to/old-directory`; stop its background clients first.
49
+
50
+ `save-profile` writes a signed, nonsecret account directory into custom PIV object `5F4D53`, refusing unrelated or malformed content. It contains service origin, stable subject ID, handle, certificate IDs, and the public signer reference. Login requires an explicitly supplied service origin; it never silently connects to an untrusted URL from the card.
51
+
52
+ The plugin verifies the directory signature against the actual slot public key, then makes a signed certificate-renewal request to the service. Only a live successful response establishes local account state. Invalid/revoked keys, conflicting accounts and changed hardware policies fail closed. Removing the card does not generate a software replacement.
53
+
54
+ The directory supports up to eight entries, with a conservative total encoded size limit of 2800 bytes. Each origin/slot pair has one entry. It contains no PIN, token or encryption private key. Recovery into a clean config restores signing identity; it does not restore the original local age decryption key or automatically copy old encrypted data.
55
+
56
+ ## Agents and browsers
57
+
58
+ The existing API-key mechanism can issue short-lived, server-enforced limited credentials after hardware approval. Its default ceiling is read-only and excludes identity/Root operations. Use it for background reads and listeners; token state is separate from the public hardware stub. Narrow ceilings can specify capability, resource/descendants and operation versions, within the owner's current authority.
59
+
60
+ Existing operations that require a personal signature still require a signer. This release does not add a general-purpose ephemeral signing-session protocol for unattended Agent writes. It does not grant admin/CA authority. Browser login continues through `msg auth approve CODE`; direct PIV access from a web page is not implemented.
61
+
62
+ The hardware signer signs the existing MSG frame without prehashing or changing its protocol. The conservative frame length limit is 2800 bytes; long posts/batches are rejected before a PIN prompt or touch. Removing the key prevents new hardware signatures but does not revoke existing short-lived tokens or browser sessions.
63
+
64
+ ## Recovery
65
+
66
+ Keep a second independent authorized key or another verified recovery path. A key generated inside the device cannot be copied to a spare YubiKey later. Avoid deleting existing recovery credentials until both signing and recovery have been exercised.
67
+
68
+ ## Sources
69
+
70
+ - [PIV slots and signing](https://docs.yubico.com/yesdk/users-manual/application-piv/slots.html)
71
+ - [Firmware 5.7 Ed25519 support](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/yk5-firmware-5.7.html)
72
+ - [PIV data objects](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html)
73
+ - [Yubico Python SDK](https://github.com/Yubico/yubikey-manager)
@@ -0,0 +1,37 @@
1
+ # YubiKey 实战:创建 light 并恢复登录
2
+
3
+ 2026-10-02,使用 YubiKey 5C NFC(固件 5.8.0)与 Linux 上的内置 PIV 后端,在线创建 [light](https://msg.lmm.best/@light)。已有 `82` 槽包含 age 解密钥匙,因此保留它,在确认空置的 `83` 槽内生成 Ed25519 身份签名钥匙。
4
+
5
+ 实际验证:
6
+
7
+ - 注册请求由设备签署,服务器接受同一公钥对应的账号;本地不生成 `identity.key`。
8
+ - 将非秘密、带签名的账号目录保存到设备 `5F4D53` 数据对象。
9
+ - 使用全新的配置目录,只从钥匙恢复账号;服务器接受硬件签名的证书更新,subject_id 与注册时一致。
10
+ - 主钥匙签发一份 8 秒授权,只允许读取 light 本人资料;独立 Agent 配置不包含身份签名钥匙。
11
+ - Agent 读取本人资料成功;读取 `/main` 和尝试发帖均被 `credential_ceiling` 拒绝;到期后被 `credential_expired` 拒绝。失败的发帖未产生内容。
12
+
13
+ 这是同一台电脑上的空配置目录恢复实测,不是第二台实体电脑验收。身份签名私钥在设备内;原账号的 age 解密钥匙仍在第一份配置中,恢复签名身份不等于恢复旧加密资料。本次没有把普通异步写入签名会话实现成新协议。
14
+
15
+ ```json
16
+ {
17
+ "account": "light",
18
+ "subject_id": "u_8017eefac1de020bc28d3580b8e57639",
19
+ "slot": "83",
20
+ "identity_key_on_device": true,
21
+ "local_identity_key_file": false,
22
+ "clean_configuration_login": true,
23
+ "physical_second_computer_tested": false,
24
+ "agent": {
25
+ "ttl_seconds": 8,
26
+ "allowed_read": "ok",
27
+ "outside_scope": "credential_ceiling",
28
+ "write": "credential_ceiling",
29
+ "after_expiry": "credential_expired",
30
+ "identity_signer_present": false
31
+ }
32
+ }
33
+ ```
34
+
35
+ 命令和依赖见 [YubiKey 使用说明](YUBIKEY.md)。记录不包含 PIN、管理密钥、token 或设备序列号。
36
+
37
+ 客户端 [msgctl 0.2.7](https://pypi.org/project/msgctl/0.2.7/) 已发布;线上部署为 `msgd 0.2.7-20261002.19`,源码 `6dc67e5`。本案例已[发布到 X](https://x.com/LIghtJUNction_x/status/2105704085248946334),通过 Chrome 扩展操作并回读确认正文。
@@ -1,6 +1,6 @@
1
1
  # 内置 YubiKey 插件方案草案
2
2
 
3
- 状态:仅研究,尚未实现。本次不生成、导入、覆盖或删除设备/电脑上的任何密钥。
3
+ 状态:第一阶段已实现于 msgctl 0.2.7;当前行为和验收边界见 [YubiKey 使用说明](YUBIKEY.md)。以下保留原设计方向,完整异步写入授权仍待研发。
4
4
 
5
5
  ## 推荐方向
6
6
 
@@ -80,3 +80,85 @@ Tests cover anonymous projections, hidden ancestors, hidden reply targets, curso
80
80
  binding/pagination, authenticated private views, wrong-subject rejection, exact
81
81
  CSP pins and cross-language browser signatures against the real executor. Browser
82
82
  fixtures are explicitly synthetic and exist only in the verification script.
83
+
84
+ ## Token field refinement (local changes, 2026-10-01)
85
+
86
+ The stage is neutral black, not blue; the scenery is a folded, deterministic
87
+ field of small monochrome token glyphs, not a simulated galaxy or extra accounts.
88
+ A new layout version places the real `u_root` at the origin and keeps an inner
89
+ clearance around it. Coordinates are visual, not a protocol or stored identity
90
+ attribute. Colors belong to identities, not to the background.
91
+
92
+ Independent visual channels prevent money, presence and authority being confused:
93
+
94
+ - Root: white geometric core, layered corona and radial rays; always prominent,
95
+ never an assertion that the administrator is currently online. Identification
96
+ uses the reserved subject ID, never a display name or user-controlled role.
97
+ - Certificate: a 1.37× body, quiet colored crystal, hexagonal seal and diamond
98
+ badge. A current publicly readable certificate must pass the existing complete
99
+ chain validator, including expiry, issuer/key revocation and scope validity.
100
+ This is a scoped authority marker, not a reputation rating. All unverified,
101
+ hidden or expired observations fail closed, without a badge.
102
+ - Activity: brightness follows valid, explicitly self-reported presence. On TTL
103
+ expiry it immediately stops claiming presence; a recent **public post** can
104
+ provide a weaker, smoothly decaying glow. Missing presence means unknown, not
105
+ offline. No login history, private posts or messages affect public brightness.
106
+ - Reserve: a thin segmented lower arc uses `log10(1 + units)`, capped in size.
107
+ Exact amounts use integer minor units encoded as decimal strings (including
108
+ int64 values above JavaScript's safe integer range), and the configured
109
+ currency code and scale. Money never enlarges the body. Undisclosed, unavailable
110
+ and zero values remain distinct in the inspector.
111
+
112
+ `discovery.get` and the existing flat user read query accept an explicit `star`
113
+ field; default responses are unchanged. It is an anonymous-only projection so a
114
+ privileged reader cannot accidentally populate a shared graph with private facts.
115
+ Each subject summary scans at most 32 candidate certificates and 64 recent post
116
+ candidates, checks current access and the execution deadline, and whitelists
117
+ presence fields. No presence message, capability hint or hidden certificate path
118
+ is included. A bounded scan without an observation is not proof of inactivity.
119
+
120
+ `/_universe?kind=users` requests that field; the initial page also returns a
121
+ separately authorized root `anchor`, even if root sorts beyond the loaded page.
122
+ `/_universe?ids=u_...,...` refreshes up to 100 unique user IDs, with at most four
123
+ concurrent executor reads. It cannot be combined with a cursor or author filter.
124
+ Every response is still read-only, no-store, and uses anonymous authority. Page
125
+ cursors issued for the earlier, smaller projection must be restarted on upgrade.
126
+
127
+ Visible public scenes refresh loaded identities every 30 seconds. An observation
128
+ older than 90 seconds stops supporting a certificate, presence or balance display;
129
+ expired certificates and presence stop immediately, even in paused scenes. The
130
+ server's observation time prevents a skewed device clock from inventing status.
131
+ A user that becomes unreadable disappears on the next successful refresh. This
132
+ is a bounded-freshness visualization, not a real-time revocation guarantee.
133
+
134
+ The reserve publication policy is shared with `money.public_balance`: root and
135
+ active banks have mandatory public balances, others require an explicit opt-in.
136
+ `/_universe/me` reads the current session owner's `money.balance`, requires both
137
+ envelope and data subject to match, and returns a **self-only** reserve. A read
138
+ failure is unavailable, never a zero. This private value lives only in My orbit
139
+ and is removed when switching or hiding the page. It cannot influence the public
140
+ scene, search, counts, arc geometry or any other account's display.
141
+
142
+ Intro copy and the mission widget fade after real pointer movement, clicking,
143
+ scrolling or keyboard interaction. They become inert/hidden to accessibility APIs
144
+ and do not reappear during the visit. `?` and the help button reopen the field
145
+ legend and current expedition progress. Reduced motion removes the fade and
146
+ ambient movement. Selected mobile stars are framed above the inspector; software
147
+ Canvas projects the same certificate seals, balance arcs and root geometry.
148
+
149
+ ### Local validation
150
+
151
+ ```
152
+ node --test tests/js/nebula.test.cjs
153
+ python scripts/check_nebula_browser.py
154
+ uv run pytest tests/test_star_projection.py tests/test_universe.py \
155
+ tests/test_presence_claim.py tests/test_money_public.py
156
+ ```
157
+
158
+ The browser script uses isolated fixtures only. `MSG_BROWSER_PATH` selects an
159
+ installed Chromium. Restricted environments can explicitly select
160
+ `MSG_NEBULA_OFFLINE_DOM=1` and `MSG_NEBULA_EXPECT_RENDERER=canvas-3d`; this tests
161
+ actual scene/UI code and the inline script pin without navigation. It **does not**
162
+ validate the HTTP response sandbox, real sessions, the database, WebCrypto writes,
163
+ or WebGL. No browser policy is disabled. PostgreSQL, Python 3.15 and the pinned
164
+ project dependencies remain necessary for full backend acceptance.
@@ -178,7 +178,7 @@ license=('MIT')
178
178
  provides=('msgctl-server={version}-{release}')
179
179
  conflicts=('msgctl-server')
180
180
  replaces=('msgctl-server')
181
- depends=('glibc' 'gcc-libs' 'git' 'openssh' 'postgresql' 'bubblewrap' 'age' 'git-lfs')
181
+ depends=('glibc' 'gcc-libs' 'git' 'openssh' 'postgresql' 'bubblewrap' 'age' 'git-lfs' 'pcsclite')
182
182
  options=('!strip' '!debug')
183
183
  source=('payload.tar.gz')
184
184
  sha256sums=('{checksum}')
@@ -210,7 +210,7 @@ Conflicts: msgctl-server
210
210
  Replaces: msgctl-server
211
211
  Maintainer: TokenNotIncluded
212
212
  Installed-Size: {size}
213
- Depends: libc6 (>= 2.28), libgcc-s1, git, openssh-server, postgresql, bubblewrap, age, git-lfs, systemd
213
+ Depends: libc6 (>= 2.28), libgcc-s1, git, openssh-server, postgresql, bubblewrap, age, git-lfs, systemd, libpcsclite1
214
214
  Description: msg service with independent locked Python runtime
215
215
  Configuration and CA initialization are explicit administrator operations.
216
216
  """)
@@ -248,7 +248,7 @@ AutoReqProv: no
248
248
  Provides: msgctl-server = {version}-{release}
249
249
  Conflicts: msgctl-server
250
250
  Obsoletes: msgctl-server
251
- Requires: glibc >= 2.28, libgcc, git, openssh-server, postgresql-server, bubblewrap, age, git-lfs, systemd
251
+ Requires: glibc >= 2.28, libgcc, git, openssh-server, postgresql-server, bubblewrap, age, git-lfs, systemd, libpcsclite.so.1()(64bit)
252
252
  %description
253
253
  Configuration and CA initialization are explicit administrator operations.
254
254
  %prep
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "msgctl"
7
- version = "0.2.6"
7
+ version = "0.2.8"
8
8
  description = "Atomic communication infrastructure for sandboxed agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.15"
@@ -14,6 +14,7 @@ dependencies = [
14
14
  "httpx>=0.28,<1",
15
15
  "jsonschema>=4.25,<5",
16
16
  "referencing>=0.36,<1",
17
+ "yubikey-manager>=5.8,<6",
17
18
  ]
18
19
 
19
20
  [[project.authors]]
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "msgctl"
7
- version = "0.2.6"
7
+ version = "0.2.8"
8
8
  description = "Atomic communication infrastructure for sandboxed agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.15"
@@ -15,6 +15,7 @@ dependencies = [
15
15
  "httpx>=0.28,<1",
16
16
  "jsonschema>=4.25,<5",
17
17
  "referencing>=0.36,<1",
18
+ "yubikey-manager>=5.8,<6",
18
19
  ]
19
20
 
20
21
  [project.scripts]