gabriel / muse public
feat patch sign task/supercharge-sign #1 / 1
AI Agent gabriel · 162 days ago · Apr 18, 2026 · Diff

feat(sign): add elapsed_ms/exit_code envelope to all JSON paths, fix text-mode stdout bleed

- Add import time + _elapsed() closure to run_header, run_verify, run_request, run_payment - Inject elapsed_ms + exit_code into every --json output path (header, verify, payment, request) - Fix run_verify: exit_code now included in JSON (was absent) - Fix run_payment text mode: signature no longer bleeds to stdout; all info goes to stderr - Remove dead _emit() stub (text-mode branch did nothing) - Update module docstring JSON schemas to include elapsed_ms/exit_code - Add tests/test_cmd_sign_hardening.py (21 tests covering all JSON envelope paths) - Update test_cmd_sign.py: test_text_output_prints_signature_to_stdout → stderr-only assertion

MWP protocol audit: canonical_message() already binds algorithm (first line) and host — downgrade protection confirmed present. No algo_type additions needed.

sha256:9af9c8ad58e5b13fd3f1ebb77ad7923c443573a1cb323bca9f56c98ac4c3f8b4 sha
+47 ~5 −2 symbols
sha256:01a0ee57edbc9aae73a910cec3a7e70f628f727779803886daa25991708a0f1b snapshot
+47
symbols added
~5
symbols modified
−2
symbols removed
0
dead code introduced
Semantic Changes 54 symbols
~ tests/test_cmd_sign_hardening.py .py 45 symbols added
+ TestAlgorithmDowngradeProtection class class TestAlgorithmDowngradeProtection L421–459
+ test_algorithm_is_first_line method method test_algorithm_is_first_line L428–435
+ test_custom_algorithm_is_bound method method test_custom_algorithm_is_bound L437–444
+ test_different_algorithms_produce_different_messages method method test_different_algorithms_produce_different_messages L446–451
+ test_host_is_in_canonical_message method method test_host_is_in_canonical_message L453–459
+ TestElapsedAndExitCode class class TestElapsedAndExitCode L53–229
+ _header_args method method _header_args L63–78
+ _payment_args method method _payment_args L184–200
+ _verify_args method method _verify_args L111–124
+ setUp method method setUp L54–59
+ test_header_json_elapsed_ms_is_float method method test_header_json_elapsed_ms_is_float L89–97
+ test_header_json_has_elapsed_ms method method test_header_json_has_elapsed_ms L80–87
+ test_header_json_has_exit_code_zero method method test_header_json_has_exit_code_zero L99–107
+ test_payment_json_elapsed_ms_is_float method method test_payment_json_elapsed_ms_is_float L211–219
+ test_payment_json_has_elapsed_ms method method test_payment_json_has_elapsed_ms L202–209
+ test_payment_json_has_exit_code_zero method method test_payment_json_has_exit_code_zero L221–229
+ test_verify_invalid_json_has_elapsed_ms method method test_verify_invalid_json_has_elapsed_ms L152–165
+ test_verify_invalid_json_has_exit_code_nonzero method method test_verify_invalid_json_has_exit_code_nonzero L167–180
+ test_verify_valid_json_elapsed_ms_is_float method method test_verify_valid_json_elapsed_ms_is_float L143–150
+ test_verify_valid_json_has_elapsed_ms method method test_verify_valid_json_has_elapsed_ms L126–132
+ test_verify_valid_json_has_exit_code_zero method method test_verify_valid_json_has_exit_code_zero L134–141
+ TestHeaderJsonSchema class class TestHeaderJsonSchema L237–268
+ test_all_required_keys_present method method test_all_required_keys_present L245–268
+ TestPaymentJsonSchema class class TestPaymentJsonSchema L336–367
+ test_all_required_keys_present method method test_all_required_keys_present L343–367
+ TestPaymentTextMode class class TestPaymentTextMode L375–413
+ _args method method _args L379–393
+ setUp method method setUp L376–377
+ test_text_mode_stderr_has_content method method test_text_mode_stderr_has_content L406–413
+ test_text_mode_stdout_is_empty method method test_text_mode_stdout_is_empty L395–404
+ TestVerifyJsonSchema class class TestVerifyJsonSchema L276–328
+ setUp method method setUp L279–284
+ test_invalid_has_all_required_keys method method test_invalid_has_all_required_keys L306–328
+ test_valid_has_all_required_keys method method test_valid_has_all_required_keys L286–304
+ _make_header function function _make_header L42–45
+ _make_signing function function _make_signing L30–34
+ _public_key_b64 function function _public_key_b64 L37–39
+ annotations import import annotations L14–14
+ argparse import import argparse L16–16
+ base64 import import base64 L17–17
+ io import import io L18–18
+ json import import json L19–19
+ patch import import patch L22–22
+ time import import time L20–20
+ unittest import import unittest L21–21
~ muse/cli/commands/sign.py .py 1 symbol added, 1 symbol removed, 4 symbols modified
− _emit function function _emit L146–152
+ time import import time L88–88
~ tests/test_cmd_sign.py .py 1 symbol added, 1 symbol removed, 1 symbol modified
− test_text_output_prints_signature_to_stdout method method test_text_output_prints_signature_to_stdout L480–493
+ test_text_output_prints_signature_to_stderr method method test_text_output_prints_signature_to_stderr L480–494
← Older Oldest on task/supercharge-sign
All commits
Newer → Latest on task/supercharge-sign

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:9af9c8ad58e5b13fd3f1ebb77ad7923c443573a1cb323bca9f56c98ac4c3f8b4 --body "your comment"