<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="41" time="10.205" timestamp="2026-10-28T15:47:09.609936+00:00" hostname="Mac"><testcase classname="tests.test_portal_access" name="test_exact_customer_invitations_and_private_local_capture" time="0.270" /><testcase classname="tests.test_portal_access" name="test_non_example_and_stale_invites_are_rejected" time="0.181" /><testcase classname="tests.test_portal_access" name="test_setup_single_use_concurrent_atomic_and_exact_customer" time="0.259" /><testcase classname="tests.test_portal_access" name="test_old_setup_code_cannot_survive_changes[expired]" time="0.175" /><testcase classname="tests.test_portal_access" name="test_old_setup_code_cannot_survive_changes[reissue]" time="0.178" /><testcase classname="tests.test_portal_access" name="test_old_setup_code_cannot_survive_changes[revoke]" time="0.175" /><testcase classname="tests.test_portal_access" name="test_old_setup_code_cannot_survive_changes[contact]" time="0.201" /><testcase classname="tests.test_portal_access" name="test_password_portal_not_email_join_and_no_owner_login" time="0.361" /><testcase classname="tests.test_portal_access" name="test_recovery_generic_response_rotates_password_sessions_and_codes" time="0.319" /><testcase classname="tests.test_portal_access" name="test_legacy_code_now_single_use_and_preupgrade_grant_revoked" time="0.173" /><testcase classname="tests.test_portal_access" name="test_invitation_retry_contains_no_code_and_one_capture" time="0.170" /><testcase classname="tests.test_portal_access" name="test_valid_foreign_customer_response_rejected_separately_from_bad_payload[accept]" time="0.284" /><testcase classname="tests.test_portal_access" name="test_valid_foreign_customer_response_rejected_separately_from_bad_payload[decline]" time="0.247" /><testcase classname="tests.test_portal_access" name="test_quote_concurrent_opposite_responses_save_one_exact_snapshot" time="0.243" /><testcase classname="tests.test_portal_access" name="test_quote_response_requires_reviewed_content_and_current_version[patch0-422]" time="0.241" /><testcase classname="tests.test_portal_access" name="test_quote_response_requires_reviewed_content_and_current_version[patch1-409]" time="0.281" /><testcase classname="tests.test_portal_access" name="test_quote_response_requires_reviewed_content_and_current_version[patch2-409]" time="0.237" /><testcase classname="tests.test_portal_access" name="test_decline_then_revision_preserves_response_and_hides_private_revision" time="0.265" /><testcase classname="tests.test_portal_access" name="test_unknown_password_portal_login_is_rate_limited" time="0.435" /><testcase classname="tests.test_portal_access" name="test_declined_source_quote_keeps_reservation_until_owner_revision_or_cancel" time="0.448" /><testcase classname="tests.test_private_pdf" name="test_pdf_private_cross_customer_business_role_and_lifecycle" time="0.437" /><testcase classname="tests.test_private_pdf" name="test_fractional_pence_unicode_and_plain_text_are_exact" time="0.184" /><testcase classname="tests.test_private_pdf" name="test_long_document_paginated_with_headers_footer_and_final_content" time="0.243" /><testcase classname="tests.test_private_pdf" name="test_historical_brand_and_payment_wording_survive_rebranding_and_payment" time="0.360" /><testcase classname="tests.test_private_pdf" name="test_stage_request_snapshot_and_current_balance_do_not_duplicate_invoice" time="0.312" /><testcase classname="tests.test_private_pdf" name="test_existing_legacy_request_requires_explicit_owner_freeze" time="0.241" /><testcase classname="tests.test_private_pdf" name="test_numbering_concurrent_settings_preserves_all_references" time="0.357" /><testcase classname="tests.test_private_pdf" name="test_document_settings_reject_unsafe_or_ambiguous_values[patch0]" time="0.169" /><testcase classname="tests.test_private_pdf" name="test_document_settings_reject_unsafe_or_ambiguous_values[patch1]" time="0.157" /><testcase classname="tests.test_private_pdf" name="test_document_settings_reject_unsafe_or_ambiguous_values[patch2]" time="0.158" /><testcase classname="tests.test_private_pdf" name="test_document_settings_reject_unsafe_or_ambiguous_values[patch3]" time="0.159" /><testcase classname="tests.test_private_pdf" name="test_document_settings_reject_unsafe_or_ambiguous_values[patch4]" time="0.160" /><testcase classname="tests.test_private_pdf" name="test_unsupported_pdf_glyph_is_explicit_without_silent_corruption" time="0.169" /><testcase classname="tests.test_private_pdf" name="test_pdf_download_uses_no_arbitrary_image_url" time="0.172" /><testcase classname="tests.test_customers" name="test_explicit_reuse_creates_one_customer_and_many_jobs" time="0.280" /><testcase classname="tests.test_customers" name="test_public_matching_remains_separate_even_same_contact" time="0.167" /><testcase classname="tests.test_customers" name="test_customer_history_financial_totals_and_immutable_names" time="0.205" /><testcase classname="tests.test_customers" name="test_customer_edit_revokes_portal_and_reuse_exposes_only_selected_customer" time="0.186" /><testcase classname="tests.test_customers" name="test_customer_routes_business_csrf_portal_and_unknown_fields" time="0.217" /><testcase classname="tests.test_customers" name="test_reviewed_bare_enquiry_link_preserves_customers_and_audit" time="0.194" /><testcase classname="tests.test_customers" name="test_link_blocks_document_cost_portal_state_and_false_confirmation" time="0.249" /></testsuite></testsuites>