msgctl 0.2.6__tar.gz → 0.2.7__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.
- {msgctl-0.2.6 → msgctl-0.2.7}/CHANGELOG.md +4 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/PKG-INFO +6 -3
- {msgctl-0.2.6 → msgctl-0.2.7}/README.md +4 -2
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CLIENT_INSTALLATION.md +3 -3
- msgctl-0.2.7/docs/YUBIKEY.md +66 -0
- msgctl-0.2.7/docs/YUBIKEY_CASE.md +35 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/YUBIKEY_DESIGN.md +1 -1
- {msgctl-0.2.6 → msgctl-0.2.7}/packaging/build-native.py +3 -3
- {msgctl-0.2.6 → msgctl-0.2.7}/pyproject.toml +2 -1
- {msgctl-0.2.6 → msgctl-0.2.7}/pyproject.toml.orig +2 -1
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/__init__.py +1 -1
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/cli.py +7 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client.py +26 -3
- msgctl-0.2.7/src/msg/client_yubikey.py +467 -0
- msgctl-0.2.7/tests/test_client_yubikey.py +184 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/uv.lock +173 -1
- {msgctl-0.2.6 → msgctl-0.2.7}/.python-version +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/CONTRIBUTING.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/SECURITY.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/conformance/test_token_budget.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/conformance/test_transports.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/conftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/README.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/hosting-role.sql +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/hosting.example.toml +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/mail.example.toml +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/msgd-hosting.service +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/msgd-worker.service +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/msgd-worker@.service +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/msgd.service +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/msgd@.service +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/nginx-shared-http-logging.conf +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/nginx.conf +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/prepare-hosting-content.sh +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/prepare-instance.sh +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/prepare-service.sh +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/deploy/sshd_config +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ARCHITECTURE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ARCHITECTURE_PROGRESS_20260929.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ARCHITECTURE_REUSE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/AUTHORIZATION_SOURCES.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/BOUNTY_ACCEPTANCE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CLIENT_BOUNDARY_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CLIENT_CONNECTIONS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CLIENT_PART_BYTES_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CLI_FIELD_SELECTION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/COMPLETE_RECOVERY_PROOF.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CREDENTIAL_DELIVERY.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/CUSTODIAL_HISTORY.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/C_READ_ACCEPTANCE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/DEPLOYMENT.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/DESIGN_CHANGE_REQUESTS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/DESIGN_CONTRACT_INVENTORY.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/FILESYSTEM_LAYOUT.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/FOLLOW_AND_FEED.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/GIT_BOUNDARY_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/HOSTING_AUTHORITY_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/HOSTING_RUNTIME.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/HOSTING_RUNTIME_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/IMPLEMENTATION_STATUS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/INTEGRATION_PROGRESS_20260929.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/INTEGRATION_REGRESSION_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ISSUES_68_70_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ISSUES_78_80_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ISSUE_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ISSUE_RESOLUTION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/ITERATION_PLAN.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/LEDGER_MIGRATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/LEGACY_GIT_MIGRATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/LEGACY_IDENTITY_ARCHIVE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/LEGACY_SQLITE_PRESERVATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/LOCAL_VERIFICATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/MANAGED_CHECKOUT.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/MARKET_BOUNDARY_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/MARKET_CLEARING.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/MARKET_CONTRACTS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/METADATA_SESSION_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/NATIVE_PACKAGES.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/NEW_ROOT_LEGACY_IMPORT_RUNBOOK.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/OAUTH.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/OFFER_ORDER_COMPATIBILITY.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/OFFER_RESOURCE_MIGRATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/POST_SUMMARIES.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/PROTOCOLS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/QUALITY_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/READ_ENTRY_ACCEPTANCE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/RELEASE_ACCEPTANCE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/SAVED_QUERIES.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/SEARCH_QUERY_V5.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/SERVICE_ALIASES.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/SSH_GIT_LOCAL_ACCEPTANCE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/SUBAGENTS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/SUBAGENT_ACCEPTANCE_20261001.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TASK_A_RECOVERY_20260928.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TASK_A_VERIFICATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TASK_C_EVIDENCE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TEMPORARY_UPGRADE.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TERMINAL_DEMO.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TOKEN_DELIVERY_BOUNDARY_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TOOL_RUNNER_BOUNDARY.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TRANSFER_STATUS_PROGRESS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/TRUST_PATHS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/VERIFICATION.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/WEBSUB.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/issue-75-77-local-verification.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/post-universe.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/docs/registry-template-tool-contracts.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/audit_filesystem_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/check_client_install.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/check_installed_server.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/check_isolated_sshd.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/check_package_artifacts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/check_tool_sandbox.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/check_universe_browser.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/ci_shards.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/render_terminal_demo.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/scripts/verify_local.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/accounts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/backup_retirement.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/backups.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/config_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/content_edit_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/custodial_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/diagnostics.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/dm_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/git_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/honor_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/legacy_approval.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/market.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/market_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/money.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/offer_import.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/preflight.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/recovery_policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/recovery_proof.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/recovery_replay.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/recovery_state.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/restore_database.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/root.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/rotation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/token_delivery_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/tool_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/transfer_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/admin/upgrade_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/.github/workflows/test.yml +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/.gitignore +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/LICENSE +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/README.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/README.zh-CN.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/pyproject.toml +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/ranker.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/algorithm/tests/test_ranker.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/application.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/atomic_file.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/bootstrap.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_agent_cli.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_api_keys.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_certificates.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_collaboration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_connection.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_content.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_custodial.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_listener.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_market.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_oauth.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_output.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_recovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_secrets.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_subagents.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_subagents_remote.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_tokens.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/client_upgrade.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/config.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/config_contracts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/constants.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/batching.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/codec.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/contracts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/cursors.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/email_address.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/errors.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/events.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/execution_ports.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/executor.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/handles.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/identifiers.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/models.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/packet.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/permissions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/post_preview.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/query.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/read_query.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/registry.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/requests.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/schema_policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/schemas.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/search_query.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/tags.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/template_dsl.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/text_patch.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/tool_execution.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/core/transfer.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/daemon.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/bootstrap.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/favicon.png +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/install.sh +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/legacy/sqlite-0221.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/logo-dark.svg +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/logo.svg +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/recovery-checkpoint.example.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/recovery-checkpoint.schema.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/recovery-policy-checkpoint.schema.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/recovery-state-schema.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web-app.js +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web-font-LICENSE.txt +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web-model.js +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web-renderer.js +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web-sans-bold.woff2 +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web-sans.woff2 +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web.css +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/root-web.html +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/shortcodes.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/AGENTS.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/_index.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/auth.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/files.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/identity.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/protocol.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/read-write.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/recovery.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/security.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/data/system/rules/topics.md +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/git_publication.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/hosting.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/keystore.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/repositories.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/rss.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/ssh.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/ssh_git.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/tools.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/extensions/websub.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/hosting_runtime.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/arbitration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/catalog.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/compatibility.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/delivery_notifications.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/delivery_targets.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/email.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/entitlement_orders.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/escrow.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/ledger.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/managed_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/offer_resources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/order_records.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/order_resources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/orders.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/rationale.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/references.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/market/targets.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/oauth_config.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/achievements.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/agent_follows.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/batch.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/bot_feed.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/bounty.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/collaboration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/collaboration_resources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/common.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/communication.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/content.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/custodial_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/discovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/discussion.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/extensions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/features.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/files.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/following.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/hosting_capacity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/identity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/mail_views.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/money.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/oauth_identity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/offers.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/orders.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/profile.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/proposals.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/read_predicates.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/receipts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/recovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/saved_queries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/schemas.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/sharing.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/store.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/system.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/transfer.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/plugins/watches.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/py.typed +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/age_keys.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/authentication.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/authorization.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/backup_retirement.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/capabilities.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/certificates.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/crypto.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/custodial_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/custodial_protocol.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/custody_history.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/network.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/oauth.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/quarantine.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/root_files.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/rotation_journal.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/sealed_box.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/sharing_policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/token_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/trust_files.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/security/vault.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/service_origin.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/capacity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/custodial_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/git.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/ledger_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_git_capture.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_git_import.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_git_rehearsal.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_identity_plan.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_rehearsal.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_resource_import.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/legacy_sqlite.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/market_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/postgres.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/query.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/read_only.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/session.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/sqlite.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/topic_event_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/storage/valkey_bus.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/browser_login.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/browser_palette.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/browser_style.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/client.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/dictionary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/git_http.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/graphql.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/home_art.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/home_page.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/http.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/http_common.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/http_routes.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/legacy_content_http.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/mcp.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/mcp_protocol.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/oauth_http.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/packet.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/permissions_page.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/read_tree_path.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/register_page.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/stdio.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/subject_views.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/universe.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/url_safety.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/transports/webmcp.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/tui.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/tui_i18n.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/effects.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/leases.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/mail.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/maintenance.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/sandbox.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/sandbox_child.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/src/msg/workers/webhook.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/conftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/fixtures/create_legacy_market.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/fixtures/legacy_market_source.json +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/fixtures/legacy_sqlite_0221.sql +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/http_read_cache_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/__init__.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/conftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_content_patch_contract.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_lfs_integrity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_lfs_migration_contract.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_read_query_tree.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_read_tree_transports.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_revision_signature_fields.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_text_patch_formats.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/issue_78_80/test_tree_query_ref.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/read_only_evidence.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_access_log_secret_redaction.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_account_archive.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_achievement_concurrency.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_achievement_context_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_achievement_pins.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_achievements.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_agent_entry.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_agent_follows.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_architecture_ports.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ascii_hero.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_attachment_http_cache.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_authority_snapshot_drift.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_authorization.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_authorization_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_authorization_recovery_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_authorization_sources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_backup_daemon.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_backup_drill.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_backup_policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_backup_retirement_attestation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_backup_retirement_cli.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_batch.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_batch_secret_release.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_bot_feed.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_bounty.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_bounty_commit_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_bounty_escrow_binding.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_bounty_public_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_bounty_snapshot_integrity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_branding.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_browser_html.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_browser_refinement.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_browser_workspace.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ca_depth.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_canonical_post_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_capability_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_capacity_bounds.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_checkout_decision_integrity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ci_shards.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_cursor_output.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_dm.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_hosting.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_json_fields.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_legacy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_recovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_cli_search_grep.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_agent_cli.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_connection.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_installer.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_listener.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_output_formats.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_part_bytes.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_response_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_secrets.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_subagents.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_subagents_remote.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_client_token_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_collaboration_current_visibility.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_collaboration_list_bounds.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_collaboration_list_deadline.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_collaboration_resource_surfaces.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_collaboration_resources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_collaboration_surfaces.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_complete_recovery_proof.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_config_safety.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_configuration_field_contracts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_content_edit_check.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_credential_delivery_contract.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_credential_delivery_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_credential_recovery_window.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_credential_upgrade_interleave.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_client_upgrade.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_historical_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_inventory_ack.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_rewrap.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_schema_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_upgrade.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custodial_vault.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_custody_exit_evidence.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_delivery_target_regression.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_dictionary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_dictionary_route.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_dm.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_dm_selftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_effect_completion_fencing.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_effect_lease_deadlines.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_effect_retry_state.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_entitlement_orders.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_error_messages.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_escrow_decision_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_escrow_decisions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_execution_composition.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_extensions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_feature_manifest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_file_copy_integrity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_file_operations.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_fixture_collection.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_following.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_foundation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_get_only_write.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_git_http_push.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_git_lfs.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_git_selftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_git_transport_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_graceful_shutdown.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_handoff_lease.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hex_post_views.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_home_channels.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_honor_diagnostics.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_addressable_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_alias_ingress.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_read_permissions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_runtime.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_runtime_authority.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_runtime_isolation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_hosting_same_origin.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_http.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_http_body_integrity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_http_effect_order.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_http_range_bounds.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_identity_handle_rename.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_identity_keys.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_independent_share_after_move.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_lease_list_bounds.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_lease_list_deadline.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ledger_account_isolation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ledger_accounts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ledger_migration_json.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ledger_migration_references.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_approval.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_content_http.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_directive.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_git_import.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_identity_plan.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_ledger_snapshot.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_resource_import.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_routes_removed.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_secret_entrypoints.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_share_source_isolation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_sqlite_preservation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_legacy_token_release.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_lexical_search_grep.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_lfs_shared_gc_quota.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_linkset_diff.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_local_postgres_fixtures.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_local_verification.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_managed_checkout.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_manifest_feature_linkage.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_markdown_redirect.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_71.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_72.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_account_scope.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_arbitration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_cli_bindings.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_compatibility_reads.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_contracts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_explicit_acceptance.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_integration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_lease_deadlines.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_manual_flow.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_notification_reuse.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_rationale.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_recovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_market_redemption.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_metadata_session_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_money_admin.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_money_config.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_money_core.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_money_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_money_public.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_native_git_read_only.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_nested_read_query.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_network_url_ports.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_nginx_secret_logs.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_notes_todos.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_oauth.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_oauth_authority.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_oauth_browser_integrity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_oauth_browser_regressions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_oauth_custodial_ceiling.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_offer_compatibility_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_offer_import.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_offer_resource_writer.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_offers.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_online_ca_policy.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_online_issuer.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_operations_admin.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_order_paths.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_order_resources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_orders.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_organization_governance.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_pagination.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_passive_get_guard.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_passive_ingress_priority.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_patch_rebase_identity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_path_read_query.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_personal_content_signatures.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_personal_documents.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_personal_signed_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_personal_text_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_pg_config.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_pg_sql_translation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_plugin_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_post_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_post_summary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_postgres.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_presence_claim.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_profile_display.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_proposals.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_protocol_routes.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_query_ref.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_query_ref_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_cursor.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_entry_contract_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_namespace.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_only_evidence.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_projection_cache_transports.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_projection_cache_unit.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_query_cursor.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_read_query_keyset_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_receipt_effect_order.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_authority_reconcile.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_current_authority.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_envelope.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_metadata.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_policy_v2.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_runtime_generation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_recovery_safety_units.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_registry_contract_references.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_registry_operation_rules.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_registry_references.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_registry_schema_ownership.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_registry_template_tools.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_release_artifacts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_release_version.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_request_target_safety.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_resource_path_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_restore_physical_failure.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_revision_sources.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_root_rotation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_root_rotation_resume.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_root_storage_layout.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_root_web_release.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_route_effect_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_rss_query_validation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_saved_queries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_saved_query_typed_scopes.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_saved_query_watch.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_search_engine_discovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_search_phrase_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_search_source_relation_filters.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_search_spelling.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_search_suggestions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_security.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_security_patch_regressions.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_security_rollback_fences.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_security_storage_rollback.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_security_topic_events.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_security_transfer_rollback.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_server_instances.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_service.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_service_aliases.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_session_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_share_grants.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_share_grants_v2.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_share_links.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_share_source_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_share_transport_matrix.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_single_mailbox_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_smtp_socket_acceptance.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_sqlite_connection_lifecycle.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ssh_bank_grant.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ssh_process_identity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ssh_root_provisioning.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_ssh_rss.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_stable_resource_views.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_stdio_cli.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_storage_commit_faults.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_storage_layout.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_store_foundation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_subject_read_aliases.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_subject_receipts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_subject_view_effect_order.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_sync_checkpoint.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_sync_cursor.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_system_rule_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_system_rule_retirement.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_system_rules.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tags_index.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_task_a_custodial_binding.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_task_a_preflight.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_task_a_recovery_checkpoint.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_task_a_root_files.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_temporary_dual_keys.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_temporary_legacy_migration.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_temporary_signed_business.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_text_patch.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_text_patch_eof_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_text_patch_line_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_text_patch_rebase_batch.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_todo_due_inbox.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_token_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_token_delivery_boundary.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tool_feature_selftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tool_runner_contract.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tool_sandbox_acceptance.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tools.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tools_directory.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_topic_governance.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_transfer.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_transfer_endpoint.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_transfer_selftest.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_transfer_status_cursors.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_trust_path_compatibility.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tui.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tui_i18n.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tui_mailbox_selection.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tui_recovery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_tui_transport_boundaries.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_universe.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_upgrade_journal.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_upgrade_journal_file_types.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_url_secrets.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_valkey_bus.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_watch_contracts.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_watch_corruption.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_watch_surfaces.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_webhook_delivery.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_webhook_domain_events.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_webhook_identity.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_webhook_overlap.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_webhook_overlap_collation.py +0 -0
- {msgctl-0.2.6 → msgctl-0.2.7}/tests/test_websub.py +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# 变更记录
|
|
2
2
|
|
|
3
|
+
## 0.2.7 — 2026-10-02
|
|
4
|
+
|
|
5
|
+
内置 YubiKey PIV Ed25519 签名后端,默认随客户端安装。支持空槽检查、设备内生成、不可导出身份私钥、本地公钥存根、已签名钥匙账号目录及空配置目录恢复登录。使用现有签名、证书与短期只读授权契约,不新增服务器权限或无触摸主身份签名。要求 PIV 固件 5.7+ 与 PC/SC;硬件签名帧限制为 2800 字节。age 解密钥匙和一般异步写入签名会话不在本次硬件保护范围内。
|
|
6
|
+
|
|
3
7
|
## 0.2.6 — 2026-10-02
|
|
4
8
|
|
|
5
9
|
收录 0.2.5 发布后的首页 token 云、紧凑设置与 12 色配色、星图加载恢复、单个 @ 用户标签和账号显示修复。YubiKey 内置插件仍处于方案讨论阶段,本版本不实现或启用该功能。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: msgctl
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
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.
|
|
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.6**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.6` 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,7 @@ 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-
|
|
234
|
+
> **Release status (2026-10-02):** [msgctl 0.2.6](https://pypi.org/project/msgctl/0.2.6/) is published on PyPI and [GitHub](https://github.com/TokenNotIncluded/msg/releases/tag/v0.2.6). The public service runs native `msgd 0.2.6-20261002.18` from source `7887d90`; 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
235
|
|
|
235
236
|
## Development and builds
|
|
236
237
|
|
|
@@ -245,3 +246,5 @@ uv run --extra dev python scripts/check_package_artifacts.py dist
|
|
|
245
246
|
Builds use `uv_build`. Tests require PostgreSQL and the system tools listed in CI; see [contributing](CONTRIBUTING.md).
|
|
246
247
|
|
|
247
248
|
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.
|
|
249
|
+
|
|
250
|
+
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.
|
|
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.6**. For the latest client, use `uv tool install --python 3.15 --force msgctl==0.2.6` 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-
|
|
203
|
+
> **Release status (2026-10-02):** [msgctl 0.2.6](https://pypi.org/project/msgctl/0.2.6/) is published on PyPI and [GitHub](https://github.com/TokenNotIncluded/msg/releases/tag/v0.2.6). The public service runs native `msgd 0.2.6-20261002.18` from source `7887d90`; 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
|
## Development and builds
|
|
206
206
|
|
|
@@ -215,3 +215,5 @@ uv run --extra dev python scripts/check_package_artifacts.py dist
|
|
|
215
215
|
Builds use `uv_build`. Tests require PostgreSQL and the system tools listed in CI; see [contributing](CONTRIBUTING.md).
|
|
216
216
|
|
|
217
217
|
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.
|
|
218
|
+
|
|
219
|
+
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.
|
|
@@ -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
|
|
|
@@ -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.
|
|
59
|
-
`uv tool install --python 3.15 --force msgctl==0.2.
|
|
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
|
|
@@ -0,0 +1,66 @@
|
|
|
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 a separate explicit configuration directory when preserving another identity on the same service. 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 --config-dir ~/.local/share/msg-hardware/light --server https://msg.lmm.best yubikey init --slot 83
|
|
27
|
+
msg --config-dir ~/.local/share/msg-hardware/light --server https://msg.lmm.best identity new light
|
|
28
|
+
msg --config-dir ~/.local/share/msg-hardware/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
|
+
## Another computer or clean configuration
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
msg --config-dir ~/.local/share/msg-hardware/light --server https://msg.lmm.best yubikey login --slot 83
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`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.
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
## Agents and browsers
|
|
50
|
+
|
|
51
|
+
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.
|
|
52
|
+
|
|
53
|
+
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.
|
|
54
|
+
|
|
55
|
+
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.
|
|
56
|
+
|
|
57
|
+
## Recovery
|
|
58
|
+
|
|
59
|
+
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.
|
|
60
|
+
|
|
61
|
+
## Sources
|
|
62
|
+
|
|
63
|
+
- [PIV slots and signing](https://docs.yubico.com/yesdk/users-manual/application-piv/slots.html)
|
|
64
|
+
- [Firmware 5.7 Ed25519 support](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/yk5-firmware-5.7.html)
|
|
65
|
+
- [PIV data objects](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html)
|
|
66
|
+
- [Yubico Python SDK](https://github.com/Yubico/yubikey-manager)
|
|
@@ -0,0 +1,35 @@
|
|
|
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 或设备序列号。
|
|
@@ -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.
|
|
7
|
+
version = "0.2.7"
|
|
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.
|
|
7
|
+
version = "0.2.7"
|
|
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]
|
|
@@ -419,6 +419,9 @@ def parser():
|
|
|
419
419
|
from msg.client_market import add_commands
|
|
420
420
|
|
|
421
421
|
add_commands(commands)
|
|
422
|
+
from msg.client_yubikey import add_commands as add_yubikey_commands
|
|
423
|
+
|
|
424
|
+
add_yubikey_commands(commands)
|
|
422
425
|
return cli
|
|
423
426
|
|
|
424
427
|
|
|
@@ -483,6 +486,10 @@ async def run(args):
|
|
|
483
486
|
result = await run_command(client, args)
|
|
484
487
|
if args.user and command == 'login':
|
|
485
488
|
await client.require_username(args.user)
|
|
489
|
+
elif command == 'yubikey':
|
|
490
|
+
from msg.client_yubikey import run_command
|
|
491
|
+
|
|
492
|
+
result = await run_command(client, args)
|
|
486
493
|
elif command == 'api-key':
|
|
487
494
|
from msg.client_api_keys import run_command
|
|
488
495
|
|
|
@@ -135,6 +135,7 @@ class ClientState:
|
|
|
135
135
|
current.get('subject_id')
|
|
136
136
|
or current.get('token')
|
|
137
137
|
or self.paths.file('identity.key').exists()
|
|
138
|
+
or self.paths.file('hardware-signer.json').exists()
|
|
138
139
|
or self.paths.file('oauth-session.json').exists()
|
|
139
140
|
):
|
|
140
141
|
# The per-service identity is already established. A leftover
|
|
@@ -150,6 +151,7 @@ class ClientState:
|
|
|
150
151
|
self.path = self.file('client.json')
|
|
151
152
|
self.key_path = self.file('identity.key')
|
|
152
153
|
self.age_key_path = self.file('encryption.agekey')
|
|
154
|
+
self.hardware_path = self.file('hardware-signer.json')
|
|
153
155
|
self.pending_path = self.file('registration.json')
|
|
154
156
|
if self.path.exists() or self.path.is_symlink():
|
|
155
157
|
require(
|
|
@@ -174,7 +176,15 @@ class ClientState:
|
|
|
174
176
|
self.data['server'] = self.server
|
|
175
177
|
self.signer = None
|
|
176
178
|
self.encryption_recipient = None
|
|
177
|
-
if self.
|
|
179
|
+
if self.hardware_path.exists() or self.hardware_path.is_symlink():
|
|
180
|
+
from msg.client_yubikey import YubiKeySigner
|
|
181
|
+
|
|
182
|
+
require(
|
|
183
|
+
not (self.key_path.exists() or self.key_path.is_symlink()),
|
|
184
|
+
'client_key_backend_conflict',
|
|
185
|
+
)
|
|
186
|
+
self.signer = YubiKeySigner.from_descriptor(private_client_json(self.hardware_path))
|
|
187
|
+
elif self.key_path.exists() or self.key_path.is_symlink():
|
|
178
188
|
self.signer = private_identity_key(self.key_path)
|
|
179
189
|
if self.age_key_path.exists() or self.age_key_path.is_symlink():
|
|
180
190
|
require(
|
|
@@ -227,8 +237,21 @@ class ClientState:
|
|
|
227
237
|
durable_write(self.path, canonical(self.data), mode=0o600)
|
|
228
238
|
|
|
229
239
|
def save_signer(self, signer):
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
from msg.client_yubikey import YubiKeySigner
|
|
241
|
+
|
|
242
|
+
require(
|
|
243
|
+
not (
|
|
244
|
+
self.key_path.exists()
|
|
245
|
+
or self.key_path.is_symlink()
|
|
246
|
+
or self.hardware_path.exists()
|
|
247
|
+
or self.hardware_path.is_symlink()
|
|
248
|
+
),
|
|
249
|
+
'identity_key_already_exists',
|
|
250
|
+
)
|
|
251
|
+
if isinstance(signer, YubiKeySigner):
|
|
252
|
+
durable_write(self.hardware_path, canonical(signer.descriptor()), mode=0o600)
|
|
253
|
+
else:
|
|
254
|
+
durable_write(self.key_path, signer.private_bytes(), mode=0o600)
|
|
232
255
|
self.signer = signer
|
|
233
256
|
|
|
234
257
|
def ensure_encryption_key(self):
|