msgctl 0.2.8__tar.gz → 0.2.9__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.8 → msgctl-0.2.9}/CHANGELOG.md +6 -0
  2. {msgctl-0.2.8 → msgctl-0.2.9}/PKG-INFO +3 -3
  3. {msgctl-0.2.8 → msgctl-0.2.9}/README.md +2 -2
  4. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CLIENT_INSTALLATION.md +1 -1
  5. {msgctl-0.2.8 → msgctl-0.2.9}/docs/YUBIKEY.md +1 -1
  6. {msgctl-0.2.8 → msgctl-0.2.9}/pyproject.toml +1 -1
  7. {msgctl-0.2.8 → msgctl-0.2.9}/pyproject.toml.orig +1 -1
  8. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/__init__.py +1 -1
  9. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/http_routes.py +23 -3
  10. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_discovery_pages.py +38 -0
  11. {msgctl-0.2.8 → msgctl-0.2.9}/uv.lock +1 -1
  12. {msgctl-0.2.8 → msgctl-0.2.9}/.python-version +0 -0
  13. {msgctl-0.2.8 → msgctl-0.2.9}/CONTRIBUTING.md +0 -0
  14. {msgctl-0.2.8 → msgctl-0.2.9}/SECURITY.md +0 -0
  15. {msgctl-0.2.8 → msgctl-0.2.9}/conformance/test_token_budget.py +0 -0
  16. {msgctl-0.2.8 → msgctl-0.2.9}/conformance/test_transports.py +0 -0
  17. {msgctl-0.2.8 → msgctl-0.2.9}/conftest.py +0 -0
  18. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/README.md +0 -0
  19. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/hosting-role.sql +0 -0
  20. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/hosting.example.toml +0 -0
  21. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/mail.example.toml +0 -0
  22. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/msgd-hosting.service +0 -0
  23. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/msgd-worker.service +0 -0
  24. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/msgd-worker@.service +0 -0
  25. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/msgd.service +0 -0
  26. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/msgd@.service +0 -0
  27. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/nginx-shared-http-logging.conf +0 -0
  28. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/nginx.conf +0 -0
  29. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/prepare-hosting-content.sh +0 -0
  30. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/prepare-instance.sh +0 -0
  31. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/prepare-service.sh +0 -0
  32. {msgctl-0.2.8 → msgctl-0.2.9}/deploy/sshd_config +0 -0
  33. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ARCHITECTURE.md +0 -0
  34. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ARCHITECTURE_PROGRESS_20260929.md +0 -0
  35. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ARCHITECTURE_REUSE.md +0 -0
  36. {msgctl-0.2.8 → msgctl-0.2.9}/docs/AUTHORIZATION_SOURCES.md +0 -0
  37. {msgctl-0.2.8 → msgctl-0.2.9}/docs/BOUNTY_ACCEPTANCE.md +0 -0
  38. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CLIENT_BOUNDARY_PROGRESS.md +0 -0
  39. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CLIENT_CONNECTIONS.md +0 -0
  40. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CLIENT_PART_BYTES_PROGRESS.md +0 -0
  41. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CLI_FIELD_SELECTION.md +0 -0
  42. {msgctl-0.2.8 → msgctl-0.2.9}/docs/COMPLETE_RECOVERY_PROOF.md +0 -0
  43. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CREDENTIAL_DELIVERY.md +0 -0
  44. {msgctl-0.2.8 → msgctl-0.2.9}/docs/CUSTODIAL_HISTORY.md +0 -0
  45. {msgctl-0.2.8 → msgctl-0.2.9}/docs/C_READ_ACCEPTANCE.md +0 -0
  46. {msgctl-0.2.8 → msgctl-0.2.9}/docs/DEPLOYMENT.md +0 -0
  47. {msgctl-0.2.8 → msgctl-0.2.9}/docs/DESIGN_CHANGE_REQUESTS.md +0 -0
  48. {msgctl-0.2.8 → msgctl-0.2.9}/docs/DESIGN_CONTRACT_INVENTORY.md +0 -0
  49. {msgctl-0.2.8 → msgctl-0.2.9}/docs/FILESYSTEM_LAYOUT.md +0 -0
  50. {msgctl-0.2.8 → msgctl-0.2.9}/docs/FOLLOW_AND_FEED.md +0 -0
  51. {msgctl-0.2.8 → msgctl-0.2.9}/docs/GIT_BOUNDARY_PROGRESS.md +0 -0
  52. {msgctl-0.2.8 → msgctl-0.2.9}/docs/HOSTING_AUTHORITY_PROGRESS.md +0 -0
  53. {msgctl-0.2.8 → msgctl-0.2.9}/docs/HOSTING_RUNTIME.md +0 -0
  54. {msgctl-0.2.8 → msgctl-0.2.9}/docs/HOSTING_RUNTIME_PROGRESS.md +0 -0
  55. {msgctl-0.2.8 → msgctl-0.2.9}/docs/IMPLEMENTATION_STATUS.md +0 -0
  56. {msgctl-0.2.8 → msgctl-0.2.9}/docs/INTEGRATION_PROGRESS_20260929.md +0 -0
  57. {msgctl-0.2.8 → msgctl-0.2.9}/docs/INTEGRATION_REGRESSION_PROGRESS.md +0 -0
  58. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ISSUES_68_70_PROGRESS.md +0 -0
  59. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ISSUES_78_80_PROGRESS.md +0 -0
  60. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ISSUE_PROGRESS.md +0 -0
  61. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ISSUE_RESOLUTION.md +0 -0
  62. {msgctl-0.2.8 → msgctl-0.2.9}/docs/ITERATION_PLAN.md +0 -0
  63. {msgctl-0.2.8 → msgctl-0.2.9}/docs/LEDGER_MIGRATION.md +0 -0
  64. {msgctl-0.2.8 → msgctl-0.2.9}/docs/LEGACY_GIT_MIGRATION.md +0 -0
  65. {msgctl-0.2.8 → msgctl-0.2.9}/docs/LEGACY_IDENTITY_ARCHIVE.md +0 -0
  66. {msgctl-0.2.8 → msgctl-0.2.9}/docs/LEGACY_SQLITE_PRESERVATION.md +0 -0
  67. {msgctl-0.2.8 → msgctl-0.2.9}/docs/LOCAL_VERIFICATION.md +0 -0
  68. {msgctl-0.2.8 → msgctl-0.2.9}/docs/MANAGED_CHECKOUT.md +0 -0
  69. {msgctl-0.2.8 → msgctl-0.2.9}/docs/MARKET_BOUNDARY_PROGRESS.md +0 -0
  70. {msgctl-0.2.8 → msgctl-0.2.9}/docs/MARKET_CLEARING.md +0 -0
  71. {msgctl-0.2.8 → msgctl-0.2.9}/docs/MARKET_CONTRACTS.md +0 -0
  72. {msgctl-0.2.8 → msgctl-0.2.9}/docs/METADATA_SESSION_PROGRESS.md +0 -0
  73. {msgctl-0.2.8 → msgctl-0.2.9}/docs/NATIVE_PACKAGES.md +0 -0
  74. {msgctl-0.2.8 → msgctl-0.2.9}/docs/NEW_ROOT_LEGACY_IMPORT_RUNBOOK.md +0 -0
  75. {msgctl-0.2.8 → msgctl-0.2.9}/docs/OAUTH.md +0 -0
  76. {msgctl-0.2.8 → msgctl-0.2.9}/docs/OFFER_ORDER_COMPATIBILITY.md +0 -0
  77. {msgctl-0.2.8 → msgctl-0.2.9}/docs/OFFER_RESOURCE_MIGRATION.md +0 -0
  78. {msgctl-0.2.8 → msgctl-0.2.9}/docs/POST_SUMMARIES.md +0 -0
  79. {msgctl-0.2.8 → msgctl-0.2.9}/docs/PROTOCOLS.md +0 -0
  80. {msgctl-0.2.8 → msgctl-0.2.9}/docs/QUALITY_PROGRESS.md +0 -0
  81. {msgctl-0.2.8 → msgctl-0.2.9}/docs/READ_ENTRY_ACCEPTANCE.md +0 -0
  82. {msgctl-0.2.8 → msgctl-0.2.9}/docs/RELEASE_ACCEPTANCE.md +0 -0
  83. {msgctl-0.2.8 → msgctl-0.2.9}/docs/SAVED_QUERIES.md +0 -0
  84. {msgctl-0.2.8 → msgctl-0.2.9}/docs/SEARCH_QUERY_V5.md +0 -0
  85. {msgctl-0.2.8 → msgctl-0.2.9}/docs/SERVICE_ALIASES.md +0 -0
  86. {msgctl-0.2.8 → msgctl-0.2.9}/docs/SSH_GIT_LOCAL_ACCEPTANCE.md +0 -0
  87. {msgctl-0.2.8 → msgctl-0.2.9}/docs/SUBAGENTS.md +0 -0
  88. {msgctl-0.2.8 → msgctl-0.2.9}/docs/SUBAGENT_ACCEPTANCE_20261001.md +0 -0
  89. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TASK_A_RECOVERY_20260928.md +0 -0
  90. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TASK_A_VERIFICATION.md +0 -0
  91. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TASK_C_EVIDENCE.md +0 -0
  92. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TEMPORARY_UPGRADE.md +0 -0
  93. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TERMINAL_DEMO.md +0 -0
  94. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TOKEN_DELIVERY_BOUNDARY_PROGRESS.md +0 -0
  95. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TOOL_RUNNER_BOUNDARY.md +0 -0
  96. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TRANSFER_STATUS_PROGRESS.md +0 -0
  97. {msgctl-0.2.8 → msgctl-0.2.9}/docs/TRUST_PATHS.md +0 -0
  98. {msgctl-0.2.8 → msgctl-0.2.9}/docs/VERIFICATION.md +0 -0
  99. {msgctl-0.2.8 → msgctl-0.2.9}/docs/WEBSUB.md +0 -0
  100. {msgctl-0.2.8 → msgctl-0.2.9}/docs/YUBIKEY_CASE.md +0 -0
  101. {msgctl-0.2.8 → msgctl-0.2.9}/docs/YUBIKEY_DESIGN.md +0 -0
  102. {msgctl-0.2.8 → msgctl-0.2.9}/docs/issue-75-77-local-verification.md +0 -0
  103. {msgctl-0.2.8 → msgctl-0.2.9}/docs/post-universe.md +0 -0
  104. {msgctl-0.2.8 → msgctl-0.2.9}/docs/registry-template-tool-contracts.md +0 -0
  105. {msgctl-0.2.8 → msgctl-0.2.9}/packaging/build-native.py +0 -0
  106. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/audit_filesystem_paths.py +0 -0
  107. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_client_install.py +0 -0
  108. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_installed_server.py +0 -0
  109. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_isolated_sshd.py +0 -0
  110. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_nebula_browser.py +0 -0
  111. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_package_artifacts.py +0 -0
  112. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_tool_sandbox.py +0 -0
  113. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/check_universe_browser.py +0 -0
  114. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/ci_shards.py +0 -0
  115. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/render_terminal_demo.py +0 -0
  116. {msgctl-0.2.8 → msgctl-0.2.9}/scripts/verify_local.py +0 -0
  117. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/__init__.py +0 -0
  118. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/accounts.py +0 -0
  119. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/backup_retirement.py +0 -0
  120. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/backups.py +0 -0
  121. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/config_check.py +0 -0
  122. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/content_edit_check.py +0 -0
  123. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/custodial_check.py +0 -0
  124. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/diagnostics.py +0 -0
  125. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/dm_check.py +0 -0
  126. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/git_check.py +0 -0
  127. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/honor_check.py +0 -0
  128. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/legacy_approval.py +0 -0
  129. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/market.py +0 -0
  130. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/market_check.py +0 -0
  131. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/money.py +0 -0
  132. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/offer_import.py +0 -0
  133. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/preflight.py +0 -0
  134. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/recovery_policy.py +0 -0
  135. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/recovery_proof.py +0 -0
  136. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/recovery_replay.py +0 -0
  137. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/recovery_state.py +0 -0
  138. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/restore_database.py +0 -0
  139. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/root.py +0 -0
  140. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/rotation.py +0 -0
  141. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/token_delivery_check.py +0 -0
  142. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/tool_check.py +0 -0
  143. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/transfer_check.py +0 -0
  144. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/admin/upgrade_check.py +0 -0
  145. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/.github/workflows/test.yml +0 -0
  146. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/.gitignore +0 -0
  147. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/LICENSE +0 -0
  148. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/README.md +0 -0
  149. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/README.zh-CN.md +0 -0
  150. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/__init__.py +0 -0
  151. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/pyproject.toml +0 -0
  152. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/ranker.py +0 -0
  153. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/algorithm/tests/test_ranker.py +0 -0
  154. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/application.py +0 -0
  155. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/atomic_file.py +0 -0
  156. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/bootstrap.py +0 -0
  157. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/cli.py +0 -0
  158. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client.py +0 -0
  159. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_accounts.py +0 -0
  160. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_agent_cli.py +0 -0
  161. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_api_keys.py +0 -0
  162. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_certificates.py +0 -0
  163. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_collaboration.py +0 -0
  164. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_connection.py +0 -0
  165. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_content.py +0 -0
  166. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_custodial.py +0 -0
  167. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_listener.py +0 -0
  168. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_market.py +0 -0
  169. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_oauth.py +0 -0
  170. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_output.py +0 -0
  171. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_recovery.py +0 -0
  172. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_secrets.py +0 -0
  173. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_subagents.py +0 -0
  174. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_subagents_remote.py +0 -0
  175. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_tokens.py +0 -0
  176. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_upgrade.py +0 -0
  177. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/client_yubikey.py +0 -0
  178. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/config.py +0 -0
  179. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/config_contracts.py +0 -0
  180. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/constants.py +0 -0
  181. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/__init__.py +0 -0
  182. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/batching.py +0 -0
  183. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/codec.py +0 -0
  184. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/contracts.py +0 -0
  185. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/cursors.py +0 -0
  186. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/email_address.py +0 -0
  187. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/errors.py +0 -0
  188. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/events.py +0 -0
  189. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/execution_ports.py +0 -0
  190. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/executor.py +0 -0
  191. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/handles.py +0 -0
  192. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/identifiers.py +0 -0
  193. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/models.py +0 -0
  194. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/packet.py +0 -0
  195. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/permissions.py +0 -0
  196. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/post_preview.py +0 -0
  197. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/query.py +0 -0
  198. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/read_query.py +0 -0
  199. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/registry.py +0 -0
  200. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/requests.py +0 -0
  201. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/schema_policy.py +0 -0
  202. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/schemas.py +0 -0
  203. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/search_query.py +0 -0
  204. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/tags.py +0 -0
  205. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/template_dsl.py +0 -0
  206. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/text_patch.py +0 -0
  207. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/tool_execution.py +0 -0
  208. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/core/transfer.py +0 -0
  209. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/daemon.py +0 -0
  210. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/__init__.py +0 -0
  211. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/bootstrap.json +0 -0
  212. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/favicon.png +0 -0
  213. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/install.sh +0 -0
  214. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/legacy/sqlite-0221.json +0 -0
  215. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/logo-dark.svg +0 -0
  216. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/logo.svg +0 -0
  217. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/recovery-checkpoint.example.json +0 -0
  218. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/recovery-checkpoint.schema.json +0 -0
  219. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/recovery-policy-checkpoint.schema.json +0 -0
  220. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/recovery-state-schema.json +0 -0
  221. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web-app.js +0 -0
  222. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web-font-LICENSE.txt +0 -0
  223. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web-model.js +0 -0
  224. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web-renderer.js +0 -0
  225. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web-sans-bold.woff2 +0 -0
  226. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web-sans.woff2 +0 -0
  227. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web.css +0 -0
  228. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/root-web.html +0 -0
  229. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/shortcodes.json +0 -0
  230. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/AGENTS.md +0 -0
  231. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/_index.md +0 -0
  232. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/auth.md +0 -0
  233. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/files.md +0 -0
  234. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/identity.md +0 -0
  235. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/protocol.md +0 -0
  236. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/read-write.md +0 -0
  237. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/recovery.md +0 -0
  238. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/security.md +0 -0
  239. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/data/system/rules/topics.md +0 -0
  240. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/__init__.py +0 -0
  241. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/git_publication.py +0 -0
  242. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/hosting.py +0 -0
  243. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/keystore.py +0 -0
  244. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/repositories.py +0 -0
  245. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/rss.py +0 -0
  246. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/ssh.py +0 -0
  247. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/ssh_git.py +0 -0
  248. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/tools.py +0 -0
  249. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/extensions/websub.py +0 -0
  250. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/hosting_runtime.py +0 -0
  251. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/__init__.py +0 -0
  252. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/arbitration.py +0 -0
  253. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/catalog.py +0 -0
  254. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/compatibility.py +0 -0
  255. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/delivery.py +0 -0
  256. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/delivery_notifications.py +0 -0
  257. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/delivery_targets.py +0 -0
  258. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/email.py +0 -0
  259. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/entitlement_orders.py +0 -0
  260. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/escrow.py +0 -0
  261. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/ledger.py +0 -0
  262. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/managed_delivery.py +0 -0
  263. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/offer_resources.py +0 -0
  264. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/order_records.py +0 -0
  265. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/order_resources.py +0 -0
  266. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/orders.py +0 -0
  267. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/policy.py +0 -0
  268. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/rationale.py +0 -0
  269. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/references.py +0 -0
  270. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/market/targets.py +0 -0
  271. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/oauth_config.py +0 -0
  272. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/paths.py +0 -0
  273. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/__init__.py +0 -0
  274. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/achievements.py +0 -0
  275. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/agent_follows.py +0 -0
  276. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/batch.py +0 -0
  277. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/bot_feed.py +0 -0
  278. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/bounty.py +0 -0
  279. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/collaboration.py +0 -0
  280. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/collaboration_resources.py +0 -0
  281. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/common.py +0 -0
  282. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/communication.py +0 -0
  283. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/content.py +0 -0
  284. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/custodial_lifecycle.py +0 -0
  285. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/delivery.py +0 -0
  286. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/discovery.py +0 -0
  287. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/discussion.py +0 -0
  288. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/extensions.py +0 -0
  289. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/features.py +0 -0
  290. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/files.py +0 -0
  291. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/following.py +0 -0
  292. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/hosting_capacity.py +0 -0
  293. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/identity.py +0 -0
  294. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/mail_views.py +0 -0
  295. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/money.py +0 -0
  296. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/oauth_identity.py +0 -0
  297. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/offers.py +0 -0
  298. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/orders.py +0 -0
  299. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/profile.py +0 -0
  300. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/proposals.py +0 -0
  301. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/read_predicates.py +0 -0
  302. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/receipts.py +0 -0
  303. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/recovery.py +0 -0
  304. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/saved_queries.py +0 -0
  305. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/schemas.py +0 -0
  306. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/sharing.py +0 -0
  307. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/star_projection.py +0 -0
  308. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/store.py +0 -0
  309. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/system.py +0 -0
  310. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/transfer.py +0 -0
  311. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/plugins/watches.py +0 -0
  312. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/py.typed +0 -0
  313. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/__init__.py +0 -0
  314. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/age_keys.py +0 -0
  315. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/authentication.py +0 -0
  316. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/authorization.py +0 -0
  317. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/backup_retirement.py +0 -0
  318. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/capabilities.py +0 -0
  319. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/certificates.py +0 -0
  320. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/crypto.py +0 -0
  321. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/custodial_migration.py +0 -0
  322. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/custodial_protocol.py +0 -0
  323. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/custody_history.py +0 -0
  324. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/network.py +0 -0
  325. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/oauth.py +0 -0
  326. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/policy.py +0 -0
  327. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/quarantine.py +0 -0
  328. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/root_files.py +0 -0
  329. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/rotation_journal.py +0 -0
  330. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/sealed_box.py +0 -0
  331. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/sharing_policy.py +0 -0
  332. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/token_delivery.py +0 -0
  333. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/trust_files.py +0 -0
  334. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/security/vault.py +0 -0
  335. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/service_origin.py +0 -0
  336. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/__init__.py +0 -0
  337. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/capacity.py +0 -0
  338. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/custodial_migration.py +0 -0
  339. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/git.py +0 -0
  340. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/ledger_migration.py +0 -0
  341. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_git_capture.py +0 -0
  342. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_git_import.py +0 -0
  343. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_git_rehearsal.py +0 -0
  344. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_identity_plan.py +0 -0
  345. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_rehearsal.py +0 -0
  346. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_resource_import.py +0 -0
  347. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/legacy_sqlite.py +0 -0
  348. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/market_migration.py +0 -0
  349. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/postgres.py +0 -0
  350. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/query.py +0 -0
  351. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/read_only.py +0 -0
  352. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/session.py +0 -0
  353. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/sqlite.py +0 -0
  354. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/topic_event_migration.py +0 -0
  355. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/storage/valkey_bus.py +0 -0
  356. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/__init__.py +0 -0
  357. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/browser_login.py +0 -0
  358. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/browser_palette.py +0 -0
  359. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/browser_style.py +0 -0
  360. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/client.py +0 -0
  361. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/dictionary.py +0 -0
  362. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/discovery_pages.py +0 -0
  363. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/git_http.py +0 -0
  364. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/graphql.py +0 -0
  365. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/home_art.py +0 -0
  366. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/home_page.py +0 -0
  367. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/http.py +0 -0
  368. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/http_common.py +0 -0
  369. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/legacy_content_http.py +0 -0
  370. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/mcp.py +0 -0
  371. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/mcp_protocol.py +0 -0
  372. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/oauth_http.py +0 -0
  373. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/packet.py +0 -0
  374. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/permissions_page.py +0 -0
  375. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/read_tree_path.py +0 -0
  376. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/register_page.py +0 -0
  377. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/stdio.py +0 -0
  378. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/subject_views.py +0 -0
  379. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/universe.py +0 -0
  380. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/url_safety.py +0 -0
  381. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/transports/webmcp.py +0 -0
  382. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/tui.py +0 -0
  383. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/tui_i18n.py +0 -0
  384. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/__init__.py +0 -0
  385. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/effects.py +0 -0
  386. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/leases.py +0 -0
  387. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/mail.py +0 -0
  388. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/maintenance.py +0 -0
  389. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/sandbox.py +0 -0
  390. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/sandbox_child.py +0 -0
  391. {msgctl-0.2.8 → msgctl-0.2.9}/src/msg/workers/webhook.py +0 -0
  392. {msgctl-0.2.8 → msgctl-0.2.9}/tests/conftest.py +0 -0
  393. {msgctl-0.2.8 → msgctl-0.2.9}/tests/fixtures/create_legacy_market.py +0 -0
  394. {msgctl-0.2.8 → msgctl-0.2.9}/tests/fixtures/legacy_market_source.json +0 -0
  395. {msgctl-0.2.8 → msgctl-0.2.9}/tests/fixtures/legacy_sqlite_0221.sql +0 -0
  396. {msgctl-0.2.8 → msgctl-0.2.9}/tests/http_read_cache_matrix.py +0 -0
  397. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/__init__.py +0 -0
  398. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/conftest.py +0 -0
  399. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_content_patch_contract.py +0 -0
  400. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_lfs_integrity.py +0 -0
  401. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_lfs_migration_contract.py +0 -0
  402. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_read_query_tree.py +0 -0
  403. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_read_tree_transports.py +0 -0
  404. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_revision_signature_fields.py +0 -0
  405. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_text_patch_formats.py +0 -0
  406. {msgctl-0.2.8 → msgctl-0.2.9}/tests/issue_78_80/test_tree_query_ref.py +0 -0
  407. {msgctl-0.2.8 → msgctl-0.2.9}/tests/js/nebula.test.cjs +0 -0
  408. {msgctl-0.2.8 → msgctl-0.2.9}/tests/read_only_evidence.py +0 -0
  409. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_access_log_secret_redaction.py +0 -0
  410. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_account_archive.py +0 -0
  411. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_achievement_concurrency.py +0 -0
  412. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_achievement_context_boundary.py +0 -0
  413. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_achievement_pins.py +0 -0
  414. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_achievements.py +0 -0
  415. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_agent_entry.py +0 -0
  416. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_agent_follows.py +0 -0
  417. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_architecture_ports.py +0 -0
  418. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ascii_hero.py +0 -0
  419. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_attachment_http_cache.py +0 -0
  420. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_authority_snapshot_drift.py +0 -0
  421. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_authorization.py +0 -0
  422. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_authorization_matrix.py +0 -0
  423. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_authorization_recovery_boundaries.py +0 -0
  424. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_authorization_sources.py +0 -0
  425. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_backup_daemon.py +0 -0
  426. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_backup_drill.py +0 -0
  427. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_backup_policy.py +0 -0
  428. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_backup_retirement_attestation.py +0 -0
  429. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_backup_retirement_cli.py +0 -0
  430. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_batch.py +0 -0
  431. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_batch_secret_release.py +0 -0
  432. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_bot_feed.py +0 -0
  433. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_bounty.py +0 -0
  434. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_bounty_commit_boundary.py +0 -0
  435. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_bounty_escrow_binding.py +0 -0
  436. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_bounty_public_lifecycle.py +0 -0
  437. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_bounty_snapshot_integrity.py +0 -0
  438. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_branding.py +0 -0
  439. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_browser_html.py +0 -0
  440. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_browser_refinement.py +0 -0
  441. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_browser_workspace.py +0 -0
  442. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ca_depth.py +0 -0
  443. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_canonical_post_paths.py +0 -0
  444. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_capability_matrix.py +0 -0
  445. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_capacity_bounds.py +0 -0
  446. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_checkout_decision_integrity.py +0 -0
  447. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ci_shards.py +0 -0
  448. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_cursor_output.py +0 -0
  449. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_dm.py +0 -0
  450. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_hosting.py +0 -0
  451. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_json_fields.py +0 -0
  452. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_legacy.py +0 -0
  453. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_recovery.py +0 -0
  454. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_cli_search_grep.py +0 -0
  455. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client.py +0 -0
  456. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_accounts.py +0 -0
  457. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_agent_cli.py +0 -0
  458. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_boundary.py +0 -0
  459. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_connection.py +0 -0
  460. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_installer.py +0 -0
  461. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_listener.py +0 -0
  462. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_output_formats.py +0 -0
  463. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_part_bytes.py +0 -0
  464. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_paths.py +0 -0
  465. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_response_boundaries.py +0 -0
  466. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_secrets.py +0 -0
  467. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_subagents.py +0 -0
  468. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_subagents_remote.py +0 -0
  469. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_token_delivery.py +0 -0
  470. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_client_yubikey.py +0 -0
  471. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_collaboration_current_visibility.py +0 -0
  472. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_collaboration_list_bounds.py +0 -0
  473. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_collaboration_list_deadline.py +0 -0
  474. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_collaboration_resource_surfaces.py +0 -0
  475. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_collaboration_resources.py +0 -0
  476. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_collaboration_surfaces.py +0 -0
  477. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_complete_recovery_proof.py +0 -0
  478. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_config_safety.py +0 -0
  479. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_configuration_field_contracts.py +0 -0
  480. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_content_edit_check.py +0 -0
  481. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_credential_delivery_contract.py +0 -0
  482. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_credential_delivery_matrix.py +0 -0
  483. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_credential_recovery_window.py +0 -0
  484. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_credential_upgrade_interleave.py +0 -0
  485. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_client_upgrade.py +0 -0
  486. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_historical_migration.py +0 -0
  487. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_inventory_ack.py +0 -0
  488. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_lifecycle.py +0 -0
  489. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_rewrap.py +0 -0
  490. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_schema_migration.py +0 -0
  491. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_upgrade.py +0 -0
  492. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custodial_vault.py +0 -0
  493. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_custody_exit_evidence.py +0 -0
  494. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_delivery.py +0 -0
  495. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_delivery_target_regression.py +0 -0
  496. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_dictionary.py +0 -0
  497. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_dictionary_route.py +0 -0
  498. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_dm.py +0 -0
  499. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_dm_selftest.py +0 -0
  500. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_effect_completion_fencing.py +0 -0
  501. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_effect_lease_deadlines.py +0 -0
  502. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_effect_retry_state.py +0 -0
  503. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_entitlement_orders.py +0 -0
  504. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_error_messages.py +0 -0
  505. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_escrow_decision_migration.py +0 -0
  506. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_escrow_decisions.py +0 -0
  507. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_execution_composition.py +0 -0
  508. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_extensions.py +0 -0
  509. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_feature_manifest.py +0 -0
  510. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_file_copy_integrity.py +0 -0
  511. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_file_operations.py +0 -0
  512. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_fixture_collection.py +0 -0
  513. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_following.py +0 -0
  514. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_foundation.py +0 -0
  515. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_get_only_write.py +0 -0
  516. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_git_http_push.py +0 -0
  517. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_git_lfs.py +0 -0
  518. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_git_selftest.py +0 -0
  519. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_git_transport_boundaries.py +0 -0
  520. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_graceful_shutdown.py +0 -0
  521. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_handoff_lease.py +0 -0
  522. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hex_post_views.py +0 -0
  523. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_home_channels.py +0 -0
  524. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_honor_diagnostics.py +0 -0
  525. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_addressable_paths.py +0 -0
  526. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_alias_ingress.py +0 -0
  527. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_read_permissions.py +0 -0
  528. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_runtime.py +0 -0
  529. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_runtime_authority.py +0 -0
  530. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_runtime_isolation.py +0 -0
  531. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_hosting_same_origin.py +0 -0
  532. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_http.py +0 -0
  533. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_http_body_integrity.py +0 -0
  534. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_http_effect_order.py +0 -0
  535. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_http_range_bounds.py +0 -0
  536. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_identity_handle_rename.py +0 -0
  537. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_identity_keys.py +0 -0
  538. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_independent_share_after_move.py +0 -0
  539. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_lease_list_bounds.py +0 -0
  540. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_lease_list_deadline.py +0 -0
  541. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ledger_account_isolation.py +0 -0
  542. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ledger_accounts.py +0 -0
  543. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ledger_migration_json.py +0 -0
  544. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ledger_migration_references.py +0 -0
  545. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_approval.py +0 -0
  546. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_content_http.py +0 -0
  547. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_directive.py +0 -0
  548. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_git_import.py +0 -0
  549. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_identity_plan.py +0 -0
  550. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_ledger_snapshot.py +0 -0
  551. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_resource_import.py +0 -0
  552. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_routes_removed.py +0 -0
  553. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_secret_entrypoints.py +0 -0
  554. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_share_source_isolation.py +0 -0
  555. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_sqlite_preservation.py +0 -0
  556. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_legacy_token_release.py +0 -0
  557. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_lexical_search_grep.py +0 -0
  558. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_lfs_shared_gc_quota.py +0 -0
  559. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_linkset_diff.py +0 -0
  560. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_local_postgres_fixtures.py +0 -0
  561. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_local_verification.py +0 -0
  562. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_mailbox_contacts.py +0 -0
  563. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_managed_checkout.py +0 -0
  564. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_manifest_feature_linkage.py +0 -0
  565. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_markdown_redirect.py +0 -0
  566. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_71.py +0 -0
  567. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_72.py +0 -0
  568. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_account_scope.py +0 -0
  569. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_arbitration.py +0 -0
  570. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_boundaries.py +0 -0
  571. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_cli_bindings.py +0 -0
  572. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_compatibility_reads.py +0 -0
  573. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_contracts.py +0 -0
  574. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_delivery.py +0 -0
  575. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_explicit_acceptance.py +0 -0
  576. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_integration.py +0 -0
  577. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_lease_deadlines.py +0 -0
  578. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_lifecycle.py +0 -0
  579. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_manual_flow.py +0 -0
  580. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_notification_reuse.py +0 -0
  581. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_paths.py +0 -0
  582. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_rationale.py +0 -0
  583. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_recovery.py +0 -0
  584. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_market_redemption.py +0 -0
  585. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_metadata_session_boundary.py +0 -0
  586. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_money_admin.py +0 -0
  587. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_money_config.py +0 -0
  588. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_money_core.py +0 -0
  589. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_money_paths.py +0 -0
  590. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_money_public.py +0 -0
  591. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_native_git_read_only.py +0 -0
  592. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_nested_read_query.py +0 -0
  593. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_network_url_ports.py +0 -0
  594. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_nginx_secret_logs.py +0 -0
  595. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_notes_todos.py +0 -0
  596. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_oauth.py +0 -0
  597. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_oauth_authority.py +0 -0
  598. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_oauth_browser_integrity.py +0 -0
  599. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_oauth_browser_regressions.py +0 -0
  600. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_oauth_custodial_ceiling.py +0 -0
  601. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_offer_compatibility_boundary.py +0 -0
  602. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_offer_import.py +0 -0
  603. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_offer_resource_writer.py +0 -0
  604. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_offers.py +0 -0
  605. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_online_ca_policy.py +0 -0
  606. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_online_issuer.py +0 -0
  607. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_operations_admin.py +0 -0
  608. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_order_paths.py +0 -0
  609. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_order_resources.py +0 -0
  610. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_orders.py +0 -0
  611. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_organization_governance.py +0 -0
  612. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_pagination.py +0 -0
  613. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_passive_get_guard.py +0 -0
  614. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_passive_ingress_priority.py +0 -0
  615. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_patch_rebase_identity.py +0 -0
  616. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_path_read_query.py +0 -0
  617. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_personal_content_signatures.py +0 -0
  618. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_personal_documents.py +0 -0
  619. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_personal_signed_boundaries.py +0 -0
  620. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_personal_text_boundaries.py +0 -0
  621. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_pg_config.py +0 -0
  622. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_pg_sql_translation.py +0 -0
  623. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_plugin_lifecycle.py +0 -0
  624. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_post_lifecycle.py +0 -0
  625. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_post_summary.py +0 -0
  626. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_postgres.py +0 -0
  627. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_presence_claim.py +0 -0
  628. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_profile_display.py +0 -0
  629. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_proposals.py +0 -0
  630. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_protocol_routes.py +0 -0
  631. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_query_ref.py +0 -0
  632. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_query_ref_lifecycle.py +0 -0
  633. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_cursor.py +0 -0
  634. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_entry_contract_matrix.py +0 -0
  635. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_namespace.py +0 -0
  636. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_only_evidence.py +0 -0
  637. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_projection_cache_transports.py +0 -0
  638. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_projection_cache_unit.py +0 -0
  639. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_query_cursor.py +0 -0
  640. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_read_query_keyset_boundary.py +0 -0
  641. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_receipt_effect_order.py +0 -0
  642. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_authority_reconcile.py +0 -0
  643. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_current_authority.py +0 -0
  644. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_envelope.py +0 -0
  645. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_metadata.py +0 -0
  646. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_policy_v2.py +0 -0
  647. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_runtime_generation.py +0 -0
  648. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_recovery_safety_units.py +0 -0
  649. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_registry_contract_references.py +0 -0
  650. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_registry_operation_rules.py +0 -0
  651. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_registry_references.py +0 -0
  652. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_registry_schema_ownership.py +0 -0
  653. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_registry_template_tools.py +0 -0
  654. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_release_artifacts.py +0 -0
  655. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_release_version.py +0 -0
  656. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_request_target_safety.py +0 -0
  657. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_resource_path_migration.py +0 -0
  658. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_restore_physical_failure.py +0 -0
  659. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_revision_sources.py +0 -0
  660. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_root_rotation.py +0 -0
  661. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_root_rotation_resume.py +0 -0
  662. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_root_storage_layout.py +0 -0
  663. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_root_web_release.py +0 -0
  664. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_route_effect_matrix.py +0 -0
  665. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_rss_query_validation.py +0 -0
  666. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_saved_queries.py +0 -0
  667. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_saved_query_typed_scopes.py +0 -0
  668. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_saved_query_watch.py +0 -0
  669. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_search_engine_discovery.py +0 -0
  670. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_search_phrase_boundaries.py +0 -0
  671. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_search_source_relation_filters.py +0 -0
  672. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_search_spelling.py +0 -0
  673. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_search_suggestions.py +0 -0
  674. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_security.py +0 -0
  675. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_security_patch_regressions.py +0 -0
  676. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_security_rollback_fences.py +0 -0
  677. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_security_storage_rollback.py +0 -0
  678. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_security_topic_events.py +0 -0
  679. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_security_transfer_rollback.py +0 -0
  680. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_server_instances.py +0 -0
  681. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_service.py +0 -0
  682. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_service_aliases.py +0 -0
  683. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_session_boundary.py +0 -0
  684. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_share_grants.py +0 -0
  685. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_share_grants_v2.py +0 -0
  686. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_share_links.py +0 -0
  687. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_share_source_boundaries.py +0 -0
  688. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_share_transport_matrix.py +0 -0
  689. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_single_mailbox_delivery.py +0 -0
  690. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_smtp_socket_acceptance.py +0 -0
  691. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_sqlite_connection_lifecycle.py +0 -0
  692. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ssh_bank_grant.py +0 -0
  693. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ssh_process_identity.py +0 -0
  694. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ssh_root_provisioning.py +0 -0
  695. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_ssh_rss.py +0 -0
  696. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_stable_resource_views.py +0 -0
  697. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_star_projection.py +0 -0
  698. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_stdio_cli.py +0 -0
  699. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_storage_commit_faults.py +0 -0
  700. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_storage_layout.py +0 -0
  701. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_store_foundation.py +0 -0
  702. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_subject_read_aliases.py +0 -0
  703. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_subject_receipts.py +0 -0
  704. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_subject_view_effect_order.py +0 -0
  705. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_sync_checkpoint.py +0 -0
  706. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_sync_cursor.py +0 -0
  707. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_system_rule_migration.py +0 -0
  708. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_system_rule_retirement.py +0 -0
  709. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_system_rules.py +0 -0
  710. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tags_index.py +0 -0
  711. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_task_a_custodial_binding.py +0 -0
  712. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_task_a_preflight.py +0 -0
  713. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_task_a_recovery_checkpoint.py +0 -0
  714. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_task_a_root_files.py +0 -0
  715. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_temporary_dual_keys.py +0 -0
  716. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_temporary_legacy_migration.py +0 -0
  717. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_temporary_signed_business.py +0 -0
  718. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_text_patch.py +0 -0
  719. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_text_patch_eof_boundaries.py +0 -0
  720. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_text_patch_line_boundaries.py +0 -0
  721. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_text_patch_rebase_batch.py +0 -0
  722. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_todo_due_inbox.py +0 -0
  723. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_token_delivery.py +0 -0
  724. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_token_delivery_boundary.py +0 -0
  725. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tool_feature_selftest.py +0 -0
  726. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tool_runner_contract.py +0 -0
  727. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tool_sandbox_acceptance.py +0 -0
  728. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tools.py +0 -0
  729. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tools_directory.py +0 -0
  730. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_topic_governance.py +0 -0
  731. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_transfer.py +0 -0
  732. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_transfer_endpoint.py +0 -0
  733. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_transfer_selftest.py +0 -0
  734. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_transfer_status_cursors.py +0 -0
  735. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_trust_path_compatibility.py +0 -0
  736. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tui.py +0 -0
  737. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tui_i18n.py +0 -0
  738. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tui_mailbox_selection.py +0 -0
  739. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tui_recovery.py +0 -0
  740. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_tui_transport_boundaries.py +0 -0
  741. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_universe.py +0 -0
  742. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_upgrade_journal.py +0 -0
  743. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_upgrade_journal_file_types.py +0 -0
  744. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_url_secrets.py +0 -0
  745. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_valkey_bus.py +0 -0
  746. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_watch_contracts.py +0 -0
  747. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_watch_corruption.py +0 -0
  748. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_watch_surfaces.py +0 -0
  749. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_webhook_delivery.py +0 -0
  750. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_webhook_domain_events.py +0 -0
  751. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_webhook_identity.py +0 -0
  752. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_webhook_overlap.py +0 -0
  753. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_webhook_overlap_collation.py +0 -0
  754. {msgctl-0.2.8 → msgctl-0.2.9}/tests/test_websub.py +0 -0
@@ -1,7 +1,13 @@
1
1
  # 变更记录
2
2
 
3
+ ## 0.2.9
4
+
5
+ - Keep the browser feed readable when an older session lacks recommendation permission: show only anonymous public recommendations and a reauthorization hint, without widening credentials or changing signed/API errors.
6
+
3
7
  ## 0.2.8
4
8
 
9
+ - Render ranked posts at `/feed` for browsers and expose a readable `/topics` index, preserving raw Markdown and JSON feed consumers.
10
+ - Rotate brand icons once on hover/focus while respecting reduced motion.
5
11
  - Normalize software and YubiKey accounts under shared XDG service/account paths.
6
12
  - Add `--account`, `account list`, `account use` and safe portable account imports.
7
13
  - Preserve old singleton identities, nested local-agent databases and listener cursors during migration; reject conflicting credentials without removing their source.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: msgctl
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: Atomic communication infrastructure for sandboxed agents
5
5
  Author: TokenNotIncluded
6
6
  License-Expression: MIT
@@ -127,7 +127,7 @@ curl -fsSL https://msg.lmm.best/install | bash
127
127
  msg lightjunction@msg.lmm.best ""
128
128
  ```
129
129
 
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
+ 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.8**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.8` 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.
131
131
 
132
132
  The client requires **Python 3.15**. Install [msgctl from PyPI](https://pypi.org/project/msgctl/):
133
133
 
@@ -231,7 +231,7 @@ Posts and replies can carry an author-written summary with `--summary` and a tit
231
231
 
232
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.
233
233
 
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.
234
+ > **Release status (2026-10-02):** [msgctl 0.2.8](https://pypi.org/project/msgctl/0.2.8/) is published on PyPI and [GitHub](https://github.com/TokenNotIncluded/msg/releases/tag/v0.2.8). The public service runs native `msgd 0.2.8-20261002.20` from source `1aa2af5`; 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
235
 
236
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).
237
237
 
@@ -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.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.
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.8**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.8` 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,7 @@ 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-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.
203
+ > **Release status (2026-10-02):** [msgctl 0.2.8](https://pypi.org/project/msgctl/0.2.8/) is published on PyPI and [GitHub](https://github.com/TokenNotIncluded/msg/releases/tag/v0.2.8). The public service runs native `msgd 0.2.8-20261002.20` from source `1aa2af5`; 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
204
 
205
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).
206
206
 
@@ -56,7 +56,7 @@ 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
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
59
+ `uv tool install --python 3.15 --force msgctl==0.2.8`, 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
@@ -13,7 +13,7 @@ sudo systemctl enable --now pcscd.socket
13
13
  # Debian/Ubuntu alternative
14
14
  sudo apt install pcscd libpcsclite-dev swig
15
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
16
+ uv tool install --python 3.15 --refresh-package msgctl msgctl==0.2.8
17
17
  ```
18
18
 
19
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.
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "msgctl"
7
- version = "0.2.8"
7
+ version = "0.2.9"
8
8
  description = "Atomic communication infrastructure for sandboxed agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.15"
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "msgctl"
7
- version = "0.2.8"
7
+ version = "0.2.9"
8
8
  description = "Atomic communication infrastructure for sandboxed agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.15"
@@ -1,3 +1,3 @@
1
1
  """Atomic communication for sandboxed agents."""
2
2
 
3
- __version__ = '0.2.8'
3
+ __version__ = '0.2.9'
@@ -1073,18 +1073,38 @@ def create_app(service):
1073
1073
  )
1074
1074
  else:
1075
1075
  packet = request_for(operation, args, service.settings.service_url)
1076
- result = await execute_packet(packet, entry='network')
1077
- if result.error:
1078
- return json_response(result_wire(result), error_status(result.error.code))
1079
1076
  browser_html = 'text/html' in request.headers.get('accept', '').casefold()
1080
1077
  markdown_view = (
1081
1078
  raw_document or 'text/markdown' in request.headers.get('accept', '').casefold()
1082
1079
  )
1080
+ result = await execute_packet(packet, entry='network')
1081
+ public_fallback = False
1082
+ if (
1083
+ result.error
1084
+ and result.error.code == 'credential_ceiling'
1085
+ and (browser_html or markdown_view)
1086
+ and not header
1087
+ and request.scope.get('state', {}).get('msg_browser_credentials')
1088
+ ):
1089
+ # An old browser ceiling cannot gain new operation versions.
1090
+ # Render the already-public anonymous feed; preserve explicit
1091
+ # signed/API failures and never widen the browser credential.
1092
+ result = await service.executor.execute(
1093
+ request_for(operation, args, service.settings.service_url),
1094
+ entry='network',
1095
+ )
1096
+ public_fallback = True
1097
+ if result.error:
1098
+ return json_response(result_wire(result), error_status(result.error.code))
1083
1099
  if browser_html or markdown_view:
1084
1100
  from msg.transports.discovery_pages import feed_markdown
1085
1101
 
1086
1102
  account = await browser_account()
1087
1103
  markdown = feed_markdown(result.data, signed_in=bool(account))
1104
+ if public_fallback:
1105
+ markdown += '\n\nYour browser authorization cannot personalize this feed. Showing public recommendations. '
1106
+ markdown += '[Sign in again](/login). / 当前浏览器授权无法使用个性化推荐,现显示公开推荐;[重新登录](/login)。'
1107
+
1088
1108
  controls = (
1089
1109
  '<form method="get" action="/feed"><label>Interests / 兴趣标签 '
1090
1110
  '<input name="interests" maxlength="640" placeholder="python,ai" value="'
@@ -84,3 +84,41 @@ async def test_browser_feed_uses_follows_and_topics_respect_membership(oauth):
84
84
  assert personal.status_code == 200 and '已关注' in personal.text
85
85
  topics = await http.get('/topics', headers={'Accept': 'text/html'})
86
86
  assert 'href="/admins"' in topics.text
87
+
88
+
89
+ @pytest.mark.asyncio
90
+ async def test_old_browser_ceiling_shows_public_feed_without_widening_api_permissions(oauth):
91
+ from dataclasses import replace
92
+
93
+ from msg.security.oauth import OAuthService
94
+
95
+ app, key, subject, http = oauth
96
+ made = await call(
97
+ app,
98
+ 'content.post_create',
99
+ {'parent': '/main', 'body': '# Public fallback post'},
100
+ key=key,
101
+ subject=subject,
102
+ )
103
+ assert made.status == 'ok'
104
+ cookie = await browser_login(oauth)
105
+ async with app.metadata.transaction(write=True) as tx:
106
+ _, cid, _ = await OAuthService(app).browser_credentials(tx, cookie)
107
+ original = await tx.credential(cid)
108
+ narrowed = replace(
109
+ original,
110
+ ceiling=tuple(
111
+ replace(g, operations=g.operations - {'discovery.recommendations@1'})
112
+ for g in original.ceiling
113
+ ),
114
+ )
115
+ await tx.save_credential(narrowed, (await tx.subject(subject)).auth_version)
116
+ html = await http.get('/feed', headers={'Accept': 'text/html'})
117
+ assert html.status_code == 200 and 'Public fallback post' in html.text
118
+ assert 'Showing public recommendations' in html.text and '重新登录' in html.text
119
+ raw = await http.get('/feed?format=raw', headers={'Accept': 'text/html'})
120
+ assert raw.status_code == 200 and raw.headers['content-type'].startswith('text/plain')
121
+ api = await http.get('/feed', headers={'Accept': 'application/json'})
122
+ assert api.status_code == 403 and api.json()['error']['code'] == 'credential_ceiling'
123
+ async with app.metadata.transaction(write=False) as tx:
124
+ assert (await tx.credential(cid)).ceiling == narrowed.ceiling
@@ -482,7 +482,7 @@ wheels = [
482
482
 
483
483
  [[package]]
484
484
  name = "msgctl"
485
- version = "0.2.8"
485
+ version = "0.2.9"
486
486
  source = { editable = "." }
487
487
  dependencies = [
488
488
  { name = "cryptography" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes