QA验收 #9
open三方按手机号或邮箱查询专家基本资料接口
Added by Redmine Admin 23 days ago. Updated 23 days ago.
0%
Description
EQ-20261019:新增GET /internal/v1/experts/lookup/,phone/email二选一,精确主备用号码及大小写不敏感主备用邮箱。独立expert:lookup,返回Candidates专家ID、姓名、公司、职位四字段;公司职位取最近有效工作履历。多个不同专家409,无匹配404,严格参数校验,不暴露联系方式或背景费用,不改变原AI公开接口。用户授权从main新建feature/expert-contact-query并保留原.aoci/config.json;本轮仅开发验证,未授权提交/推送/上线。
RA Updated by Redmine Admin 23 days ago Actions #1
开发隔离测试证据 - EQ-20261019 - 2026-10-19¶
分支feature/expert-contact-query;非正式QA验收。SQLite内存库74项Pass;专用本地PostgreSQL16数据库87项Pass;外部网络封锁,未访问真实业务库。
| 环境/测试编号 | 预期 | 实际 | 状态 |
|---|---|---|---|
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_canonical_query_sorts_keys_and_preserves_duplicates | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_canonical_query_uses_rfc3986_space_encoding | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_disallowed_ip_is_forbidden | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_expired_timestamp_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_invalid_forwarded_ip_is_not_persisted | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_missing_scope_is_forbidden | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_reused_nonce_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_valid_signature_authenticates_application | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationAuthTests.test_wrong_signature_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationManagementTests.test_create_returns_secret_once_and_list_never_returns_it | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationManagementTests.test_non_admin_cannot_manage_applications | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests.ApplicationManagementTests.test_rotate_secret_invalidates_previous_secret | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_default_only_active_and_whitelisted_fields | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_disabled_application_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_email_is_exact_and_case_insensitive | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_existing_scopes_do_not_grant_user_directory | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_explicit_inactive_and_inactive_hidden_by_default | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_filters_combine_with_and | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_id_filter | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_invalid_query_returns_http_400 | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_name_matches_chinese_and_english | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_no_credentials_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_pagination_order_total_and_empty_page | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_read_only_route | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_replay_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_schema_preserves_envelope_parameters_and_security | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_scope_is_available_to_application_management | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_trailing_slash_optional_without_redirect | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_users.InternalUsersTests.test_wrong_signature_rejected | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_deleted_contact_and_company_are_hidden | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_deleted_duplicate_does_not_cause_ambiguity | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_disabled_app_and_disallowed_ip | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_id_lookup_whitelist | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_invalid_missing_combined_unknown_and_repeated_queries | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_missing_contact_is_404 | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_missing_credentials_bad_signature_and_replay | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_multiple_contacts_are_ambiguous_including_cross_field | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_no_company_is_hidden | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_no_write_methods_or_redirect | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_null_ordinary_fields_are_retained | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_other_scopes_do_not_grant_contact_read | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_primary_and_backup_phone_exact | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_query_only_loads_projection_fields | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_resolve_route_is_unchanged | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_same_record_matching_both_phones_is_unique | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_schema_contract | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_clients.InternalClientsTests.test_scope_available_without_automatic_grant | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_all_null_dates_have_stable_id_tiebreak | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_auth_missing_bad_signature_tampering_and_replay | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_deleted_and_null_deleted_experts_excluded | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_deleted_duplicate_does_not_make_ambiguous | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_derivative_does_not_merge_by_original_id | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_disabled_app_and_ip_restriction | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_exact_matching_and_no_phone_normalization | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_galaxy_is_not_part_of_identity_domain | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_invalid_unknown_empty_repeated_or_combined_queries | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_latest_work_not_necessarily_current_employment | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_multiple_expert_ids_email_ambiguous_ignore_case | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_multiple_expert_ids_phone_ambiguous_no_candidate_list | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_no_ai_gate_source_lock_availability_or_derivative_filter | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_no_work_experience_fields_are_null | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_non_work_deleted_null_deleted_experiences_are_ignored | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_null_and_blank_values_stay_on_same_row | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_null_dates_sort_last_and_ties_use_highest_id | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_original_routes_and_new_anchor_do_not_conflict | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_other_scopes_are_insufficient_and_no_automatic_grant | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_primary_and_backup_email_ignore_case | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_primary_and_backup_phone | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_read_only_methods_and_optional_slash | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_schema_has_four_fields_independent_scope_and_all_examples | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_single_expert_double_phone_or_email_hit_is_not_ambiguous | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_whitelist_and_only_required_columns_loaded | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.meetings.tests.MeetingApiTests.test_resolve_contact_and_ambiguity | 测试断言全部满足 | all assertions passed | Pass |
| sqlite: api.meetings.tests.MeetingApiTests.test_resolve_contact_requires_new_auth_after_number_replacement | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_canonical_query_sorts_keys_and_preserves_duplicates | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_canonical_query_uses_rfc3986_space_encoding | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_disallowed_ip_is_forbidden | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_expired_timestamp_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_invalid_forwarded_ip_is_not_persisted | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_missing_scope_is_forbidden | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_reused_nonce_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_valid_signature_authenticates_application | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationAuthTests.test_wrong_signature_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationManagementTests.test_create_returns_secret_once_and_list_never_returns_it | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationManagementTests.test_non_admin_cannot_manage_applications | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests.ApplicationManagementTests.test_rotate_secret_invalidates_previous_secret | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_deleted_contact_and_company_are_hidden | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_deleted_duplicate_does_not_cause_ambiguity | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_disabled_app_and_disallowed_ip | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_id_lookup_whitelist | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_invalid_missing_combined_unknown_and_repeated_queries | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_missing_contact_is_404 | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_missing_credentials_bad_signature_and_replay | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_multiple_contacts_are_ambiguous_including_cross_field | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_no_company_is_hidden | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_no_write_methods_or_redirect | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_null_ordinary_fields_are_retained | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_other_scopes_do_not_grant_contact_read | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_primary_and_backup_phone_exact | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_query_only_loads_projection_fields | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_resolve_route_is_unchanged | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_same_record_matching_both_phones_is_unique | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_schema_contract | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_clients.InternalClientsTests.test_scope_available_without_automatic_grant | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_all_null_dates_have_stable_id_tiebreak | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_auth_missing_bad_signature_tampering_and_replay | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_deleted_and_null_deleted_experts_excluded | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_deleted_duplicate_does_not_make_ambiguous | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_derivative_does_not_merge_by_original_id | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_disabled_app_and_ip_restriction | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_exact_matching_and_no_phone_normalization | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_galaxy_is_not_part_of_identity_domain | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_invalid_unknown_empty_repeated_or_combined_queries | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_latest_work_not_necessarily_current_employment | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_multiple_expert_ids_email_ambiguous_ignore_case | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_multiple_expert_ids_phone_ambiguous_no_candidate_list | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_no_ai_gate_source_lock_availability_or_derivative_filter | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_no_work_experience_fields_are_null | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_non_work_deleted_null_deleted_experiences_are_ignored | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_null_and_blank_values_stay_on_same_row | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_null_dates_sort_last_and_ties_use_highest_id | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_original_routes_and_new_anchor_do_not_conflict | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_other_scopes_are_insufficient_and_no_automatic_grant | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_primary_and_backup_email_ignore_case | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_primary_and_backup_phone | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_read_only_methods_and_optional_slash | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_schema_has_four_fields_independent_scope_and_all_examples | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_single_expert_double_phone_or_email_hit_is_not_ambiguous | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_expert_lookup.InternalExpertLookupTests.test_whitelist_and_only_required_columns_loaded | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_ai_only_does_not_enable_wechat_and_revocation_is_immediate | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_api_is_read_only | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_authentication_and_dedicated_scope_are_required | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_draft_archived_future_null_date_and_deleted_are_hidden | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_invalid_query_is_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_keyword_and_pagination_only_search_public_fields | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_openapi_documents_list_detail_and_scope | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_other_source_profiles_cannot_be_read_or_selected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_scope_is_available_to_application_management | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_shared_public_source_and_whitelisted_projection | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_signature_tampering_and_nonce_reuse_are_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_unavailable_source_fails_closed | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_experts.InternalExpertsTests.test_wechat_only_profile_is_not_readable_by_ai | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_default_only_active_and_whitelisted_fields | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_disabled_application_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_email_is_exact_and_case_insensitive | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_existing_scopes_do_not_grant_user_directory | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_explicit_inactive_and_inactive_hidden_by_default | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_filters_combine_with_and | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_id_filter | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_invalid_query_returns_http_400 | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_name_matches_chinese_and_english | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_no_credentials_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_pagination_order_total_and_empty_page | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_read_only_route | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_replay_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_schema_preserves_envelope_parameters_and_security | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_scope_is_available_to_application_management | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_trailing_slash_optional_without_redirect | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.application_auth.tests_internal_users.InternalUsersTests.test_wrong_signature_rejected | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.meetings.tests.MeetingApiTests.test_resolve_contact_and_ambiguity | 测试断言全部满足 | all assertions passed | Pass |
| pg: api.meetings.tests.MeetingApiTests.test_resolve_contact_requires_new_auth_after_number_replacement | 测试断言全部满足 | all assertions passed | Pass |
首轮SQLite74项/PostgreSQL87项各有同一处测试断言失败:GET路由被DRF自动补HEAD,断言误判;已修测试断言,业务代码未因此调整,末轮均通过。首轮日志sqlite-run-1.log/pg-run-1.log、逐条test-cases-*-run-1.json保留。
本轮无提交、推送、生产发布或远端Apifox同步;独立QA未执行,不沿用上次客户接口QA豁免。独立只读安全review待完成。
证据目录:outputs/expert-contact-query-20261019,sqlite-final.log/pg-final.log及test-cases-sqlite.json/test-cases-pg.json。
RA Updated by Redmine Admin 23 days ago Actions #2
开发候选交付补充:6文件哈希已冻结并由协调最终重核一致;Operations独立只读安全及需求符合性审核未见明确阻断缺陷(不是正式QA验收)。报告outputs/expert-contact-query-20261019/backend-result.md、review.md,OpenAPI候选openapi.yaml。SQLite74/隔离PG87项通过;本任务临时PG容器与匿名卷已清理。分支feature/expert-contact-query,原.aoci/config.json保留。未提交/推送/发布/远端Apifox,未运行真实专家或AK查询;正式QA未执行,无本轮豁免。AOCI仍受既有治理漂移阻塞,未改写索引。
RA Updated by Redmine Admin 23 days ago Actions #3
独立只读审核与验收准备复核 - EQ-20261019 - 2026-10-19¶
固定基线4d952e3、feature/expert-contact-query;按candidate-files.json复核6文件冻结哈希一致。本轮没有新增测试执行,不重复此前SQLite74/PG87逐条开发记录,也不将开发测试改称正式QA。
- Standards轴:独立只读审核未发现可行动的P0–P3规范问题,覆盖HMAC/独立Scope、隐私投影、HTTP响应、只读边界。
- Spec轴:独立只读审核未发现可行动的需求实现问题,覆盖严格二选一参数、主备用匹配、不同专家ID歧义、删除标志、同条工作履历排序、四字段返回及旧路由。
- 两轴由隔离的辅助审核Agent对冻结代码和原始契约分别进行;未运行代码或访问真实业务数据,不是正式QA验收。
- 已有开发证据复核:SQLite74/PG87逐条JSON均Pass且case_id唯一,汇总与最终日志一致;首轮测试断言失败与末轮重测证据均保留;专用测试容器及匿名卷清理已记录。
- 当前正式QA仍未完成,未关闭需求、未调整进度;真实规模性能、实际环境业务调用及API手册验收未执行。
- 未commit/push/PR/tag/deploy,未访问真实凭据或远端Apifox,未修改业务代码或原.aoci/config.json。
证据:outputs/expert-contact-query-20261019/independent-review-20261019.md、review-inputs/、candidate-files.json、test-cases-sqlite.json、test-cases-pg.json、test-summary.json、sqlite-final.log、pg-final.log、test-container-cleanup.json。
RA Updated by Redmine Admin 23 days ago Actions #4
正式 API QA 测试结果 - EQ-20261019 - 第1轮 - 2026-10-19 Asia/Shanghai¶
- Redmine: NDB #9 https://redmine.mindsetech.com/issues/9,标题“三方按手机号或邮箱查询专家基本资料接口”。
- 执行者:EQ-20261019 independent task QA / 01a0ba71-f49e-7b23-9b69-6dc35606d65b,本轮任务级独立QA执行者,不是实现本需求的业务Agent。
- 候选:feature/expert-contact-query,基线4d952e3ccf3ce9b2fd6c34f19925fa23c2e98e1f,6文件尚未提交;哈希见下。
- 本轮范围:SQLite 76 + 专用PostgreSQL 89 = 165项实际执行;文字接入契约1项;合计166。
- 汇总:Pass 166 / Fail 0 / Blocked 0 / Skipped 0。无缺陷关联。
- 执行时间:SQLite 2026-10-19T17:03:23.925939+08:00 至 2026-10-19T17:03:27.828864+08:00;PG 2026-10-19T17:03:24.575945+08:00 至 2026-10-19T17:03:31.260555+08:00。
- 环境:SQLite内存;独立postgres:16-alpine,loopback 127.0.0.1:55489,实际test_formal_eq_20261019。仅合成TestCase专家/履历/客户和新生成合成应用AK/SK,无真实业务数据或凭据。
- 出站:两轮socket.connect/create_connection封锁非本轮专用PG;每case断言实际DB,原5432及其他容器不操作;未发生意外连接请求。
- 脚本设置:migrations禁用,按模型建测试表;这是隔离API/查询/排序验证,不是生产迁移链验收。
共享前置、步骤及证据¶
所有用例先使用自身TestCase.setUp合成前提及LocMem nonce cache。每条精确test_id、前置、步骤、语义预期、真实HTTP状态/响应字段、执行时间/DB/身份和候选哈希保存在cases-sqlite-r1.json或cases-pg-r1.json;下表编号一一对应,不覆盖开发记录。源码中的子场景随所属case执行,全部断言成立。
从canonical Backend先activate crm_backend,再以PYTHONDONTWRITEBYTECODE=1、FORMAL_EQ_DB=sqlite或pg、PYTHONPATH包含formal-qa及Backend执行formal-qa/run_formal_qa.py;labels固定保存在每轮JSON中。复跑PG须另行建立本轮隔离容器且端口/DB断言保持,不能接业务库。
证据根:outputs/expert-contact-query-20261019/formal-qa/
- cases-sqlite-r1.json / sqlite-r1.log:本轮76条;cases-pg-r1.json / pg-r1.log:本轮89条。
- run_formal_qa.py、formal_eq_settings.py、formal_extra_tests.py、expectations.json:本轮独立执行器、严格DB/外连限制、两个独立QA场景及语义预期。
- doc-review.json:文字API接入说明核对;final-integrity-cleanup.json:候选/config未变及本轮资源清理。
冻结候选哈希¶
- api/application_auth/constants.py: daccba7847a2b9d4128d160587be7fb50cefd84684cb51842dc5d8a3b8800d18
- api/application_auth/internal_urls.py: 1e5711dfc834fc838c6e74fcd5433b347f6df3f030a89e24ff762588cdf57933
- api/application_auth/internal_expert_lookup.py: 32b9a055f41bf0a3e9e232a4a87966ad251bb669a52c78b222d9f4bfc4ead2d7
- api/application_auth/tests_internal_expert_lookup.py: 38c80384348d5f41db552d27e8e38a55c8ff03067fcf172d4d87842841d8830b
- docs/specs/2026-09-01-application-auth.md: 0230cceca05f3e8e50500506ed6bc0113602cdc05c0b3d2b8410ff7acd82cc9a
- docs/specs/2026-10-19-third-party-expert-contact-lookup.md: b56f4a326618a2ade1d2428d71067b35de6b5fa918ff6d01f1faa4c196a9c3a5
逐条结果¶
| 编号 | 用例/层级 | 预期 | 本轮实际 | 状态 | 证据/缺陷 |
|---|---|---|---|---|---|
| EQ-QA-SQL-001 | ApplicationAuthTests.test_canonical_query_sorts_keys_and_preserves_duplicates / sqlite接口 | 规范签名查询串按键值排序且保留重复键,不丢失签名输入 | 本轮执行确认:规范签名查询串按键值排序且保留重复键,不丢失签名输入;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-001;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-002 | ApplicationAuthTests.test_canonical_query_uses_rfc3986_space_encoding / sqlite接口 | 规范查询串的空格使用%20,不以加号替代 | 本轮执行确认:规范查询串的空格使用%20,不以加号替代;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-002;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-003 | ApplicationAuthTests.test_disallowed_ip_is_forbidden / sqlite接口 | 签名有效但来源IP不在白名单时返回403 | 本轮执行确认:签名有效但来源IP不在白名单时返回403;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-003;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-004 | ApplicationAuthTests.test_expired_timestamp_is_rejected / sqlite接口 | 过期签名时间戳返回401 | 本轮执行确认:过期签名时间戳返回401;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-004;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-005 | ApplicationAuthTests.test_invalid_forwarded_ip_is_not_persisted / sqlite接口 | 非法转发IP不被保存为应用最后使用IP | 本轮执行确认:非法转发IP不被保存为应用最后使用IP;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-005;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-006 | ApplicationAuthTests.test_missing_scope_is_forbidden / sqlite接口 | 签名有效但缺少接口Scope时返回403 | 本轮执行确认:签名有效但缺少接口Scope时返回403;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-006;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-007 | ApplicationAuthTests.test_reused_nonce_is_rejected / sqlite接口 | 同一Nonce首次成功,重放返回401 | 本轮执行确认:同一Nonce首次成功,重放返回401;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-007;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-008 | ApplicationAuthTests.test_valid_signature_authenticates_application / sqlite接口 | 合法应用签名认证成功并返回应用身份 | 本轮执行确认:合法应用签名认证成功并返回应用身份;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-008;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-009 | ApplicationAuthTests.test_wrong_signature_is_rejected / sqlite接口 | 错误签名返回401 | 本轮执行确认:错误签名返回401;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-009;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-010 | ApplicationManagementTests.test_create_returns_secret_once_and_list_never_returns_it / sqlite接口 | 应用创建仅首次展示Secret,普通列表不返回Secret | 本轮执行确认:应用创建仅首次展示Secret,普通列表不返回Secret;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-010;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-011 | ApplicationManagementTests.test_non_admin_cannot_manage_applications / sqlite接口 | 非管理员不能创建或管理应用凭据 | 本轮执行确认:非管理员不能创建或管理应用凭据;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-011;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-012 | ApplicationManagementTests.test_rotate_secret_invalidates_previous_secret / sqlite接口 | 轮换Secret后旧签名失效,新Secret有效 | 本轮执行确认:轮换Secret后旧签名失效,新Secret有效;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-012;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-013 | InternalClientsTests.test_deleted_contact_and_company_are_hidden / sqlite接口 | 联系人或公司删除后,ID和手机号查询均404 | GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-013;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-014 | InternalClientsTests.test_deleted_duplicate_does_not_cause_ambiguity / sqlite接口 | 删除联系人、删除公司及无公司重复数据不触发歧义 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-014;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-015 | InternalClientsTests.test_disabled_app_and_disallowed_ip / sqlite接口 | 停用应用401;恢复后不允许的IP403 | GET /internal/v1/clients/:HTTP401/code=authentication_failed; GET /internal/v1/clients/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-015;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-016 | InternalClientsTests.test_id_lookup_whitelist / sqlite接口 | 联系人ID命中200且严格五字段,不返回联系方式或备注 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-016;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-017 | InternalClientsTests.test_invalid_missing_combined_unknown_and_repeated_queries / sqlite接口 | 客户查询缺失、空、非法、组合、未知或重复参数均400/INVALID_REQUEST | GET /internal/v1/clients/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-017;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-018 | InternalClientsTests.test_missing_contact_is_404 / sqlite接口 | 不存在的联系人ID返回404/CONTACT_NOT_FOUND | GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-018;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-019 | InternalClientsTests.test_missing_credentials_bad_signature_and_replay / sqlite接口 | 缺凭据、错签和Nonce重放401,首次合法调用成功 | GET /internal/v1/clients/:HTTP401/code=authentication_failed; GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-019;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-020 | InternalClientsTests.test_multiple_contacts_are_ambiguous_including_cross_field / sqlite接口 | 不同联系人跨主备用号重复时409且无data,改ID可查 | GET /internal/v1/clients/:HTTP409/code=AMBIGUOUS_CONTACT; GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-020;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-021 | InternalClientsTests.test_no_company_is_hidden / sqlite接口 | 无公司客户联系人按ID和手机号均404 | GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-021;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-022 | InternalClientsTests.test_no_write_methods_or_redirect / sqlite接口 | 客户查询支持无尾斜杠不重定向,写方法405且客户数据不变 | GET /internal/v1/clients:HTTP200/code=200; POST /internal/v1/clients/:HTTP405/code=method_not_allowed; PUT /internal/v1/clients/:HTTP405/code=method_not_allowed; PATCH /internal/v1/clients/:HTTP405/code=method_not_allowed; DELETE /internal/v1/clients/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-022;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-023 | InternalClientsTests.test_null_ordinary_fields_are_retained / sqlite接口 | 客户普通姓名、公司名和职位null时仍保留固定字段 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-023;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-024 | InternalClientsTests.test_other_scopes_do_not_grant_contact_read / sqlite接口 | client:resolve/user:read/expert:read等不授予client:read,返回403 | GET /internal/v1/clients/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-024;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-025 | InternalClientsTests.test_primary_and_backup_phone_exact / sqlite接口 | 客户主备用号精确命中200,号码子串不命中404 | GET /internal/v1/clients/:HTTP200/code=200; GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-025;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-026 | InternalClientsTests.test_query_only_loads_projection_fields / sqlite接口 | 客户ORM仅实例化id/name/company_id/position等必要投影列 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-026;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-027 | InternalClientsTests.test_resolve_route_is_unchanged / sqlite接口 | 原clients/resolve仍映射MeetingView的POST resolve_contact | 本轮执行确认:原clients/resolve仍映射MeetingView的POST resolve_contact;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-027;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-028 | InternalClientsTests.test_same_record_matching_both_phones_is_unique / sqlite接口 | 同一客户主备用号均命中时只算一个联系人 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-028;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-029 | InternalClientsTests.test_schema_contract / sqlite接口 | 客户schema有HMAC、两参数、五字段及200/400/401/403/404/405/409示例 | 本轮执行确认:客户schema有HMAC、两参数、五字段及200/400/401/403/404/405/409示例;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-029;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-030 | InternalClientsTests.test_scope_available_without_automatic_grant / sqlite接口 | client:read可显式选择,但既有client:resolve应用不自动扩权 | 本轮执行确认:client:read可显式选择,但既有client:resolve应用不自动扩权;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-030;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-031 | InternalExpertLookupTests.test_all_null_dates_have_stable_id_tiebreak / sqlite接口 | 工作履历日期全部null时稳定选最大ID的同一行公司职位 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-031;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-032 | InternalExpertLookupTests.test_auth_missing_bad_signature_tampering_and_replay / sqlite接口 | 专家lookup缺凭据、错签、签名后篡改查询及重放均401 | GET /internal/v1/experts/lookup/:HTTP401/code=authentication_failed; GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-032;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-033 | InternalExpertLookupTests.test_deleted_and_null_deleted_experts_excluded / sqlite接口 | 专家is_deleted=true或null均排除,手机号/邮箱返回404 | GET /internal/v1/experts/lookup/:HTTP404/code=EXPERT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-033;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-034 | InternalExpertLookupTests.test_deleted_duplicate_does_not_make_ambiguous / sqlite接口 | 已删除或null删除标志的重复专家不导致有效专家歧义 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-034;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-035 | InternalExpertLookupTests.test_derivative_does_not_merge_by_original_id / sqlite接口 | 派生与原专家共用号码仍按不同Candidates.id判409,不按original_id合并 | GET /internal/v1/experts/lookup/:HTTP409/code=AMBIGUOUS_EXPERT;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-035;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-036 | InternalExpertLookupTests.test_disabled_app_and_ip_restriction / sqlite接口 | 专家lookup停用应用401,IP不允许403 | GET /internal/v1/experts/lookup/:HTTP401/code=authentication_failed; GET /internal/v1/experts/lookup/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-036;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-037 | InternalExpertLookupTests.test_exact_matching_and_no_phone_normalization / sqlite接口 | 手机号和邮箱不做子串匹配;手机号不拼区号,已存国际格式精确命中 | GET /internal/v1/experts/lookup/:HTTP404/code=EXPERT_NOT_FOUND; GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-037;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-038 | InternalExpertLookupTests.test_galaxy_is_not_part_of_identity_domain / sqlite接口 | 只在Galaxy存在相同号码时lookup返回404,不混入Galaxy身份 | GET /internal/v1/experts/lookup/:HTTP404/code=EXPERT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-038;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-039 | InternalExpertLookupTests.test_invalid_unknown_empty_repeated_or_combined_queries / sqlite接口 | lookup拒绝无条件、空、首尾空白、越长、坏邮箱、组合、重复及未知参数,均400 | GET /internal/v1/experts/lookup/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-039;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-040 | InternalExpertLookupTests.test_latest_work_not_necessarily_current_employment / sqlite接口 | 取最近started_at的work履历,即使已离职也保持最近记录语义 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-040;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-041 | InternalExpertLookupTests.test_multiple_expert_ids_email_ambiguous_ignore_case / sqlite接口 | 不同专家邮箱跨主备用且大小写相异重复时返回409 | GET /internal/v1/experts/lookup/:HTTP409/code=AMBIGUOUS_EXPERT;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-041;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-042 | InternalExpertLookupTests.test_multiple_expert_ids_phone_ambiguous_no_candidate_list / sqlite接口 | 不同专家号码重复返回409/AMBIGUOUS_EXPERT,仅code/message且不泄漏候选 | GET /internal/v1/experts/lookup/:HTTP409/code=AMBIGUOUS_EXPERT;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-042;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-043 | InternalExpertLookupTests.test_no_ai_gate_source_lock_availability_or_derivative_filter / sqlite接口 | Candidates各source、锁定、不可约及派生记录均可查,不要求AI公开许可 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-043;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-044 | InternalExpertLookupTests.test_no_work_experience_fields_are_null / sqlite接口 | 无工作履历时四字段保留,公司和职位均null | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-044;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-045 | InternalExpertLookupTests.test_non_work_deleted_null_deleted_experiences_are_ignored / sqlite接口 | 教育/项目、已删和null删除标志履历不覆盖有效work记录 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-045;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-046 | InternalExpertLookupTests.test_null_and_blank_values_stay_on_same_row / sqlite接口 | 姓名null、最近履历公司null/职位空串原样保留,不跨行补旧值 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-046;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-047 | InternalExpertLookupTests.test_null_dates_sort_last_and_ties_use_highest_id / sqlite接口 | 履历日期DESC NULLS LAST,同日起点取最大ID,两个输出来自同一行 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-047;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-048 | InternalExpertLookupTests.test_original_routes_and_new_anchor_do_not_conflict / sqlite接口 | 新lookup、原公开列表/数字详情和clients/resolve路由保持,额外尾路径不匹配 | 本轮执行确认:新lookup、原公开列表/数字详情和clients/resolve路由保持,额外尾路径不匹配;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-048;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-049 | InternalExpertLookupTests.test_other_scopes_are_insufficient_and_no_automatic_grant / sqlite接口 | expert:read/client:read/user:read等不授予lookup;缺expert:lookup403且不自动增权 | GET /internal/v1/experts/lookup/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-049;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-050 | InternalExpertLookupTests.test_primary_and_backup_email_ignore_case / sqlite接口 | 专家主备用邮箱不区分大小写精确命中200且内部专家ID正确 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-050;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-051 | InternalExpertLookupTests.test_primary_and_backup_phone / sqlite接口 | 专家主备用手机号均命中200,四字段姓名公司职位与合成记录一致 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-051;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-052 | InternalExpertLookupTests.test_read_only_methods_and_optional_slash / sqlite接口 | lookup支持无尾斜杠,POST/PUT/PATCH/DELETE405且专家/履历不变 | GET /internal/v1/experts/lookup:HTTP200/code=200; POST /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed; PUT /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed; PATCH /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed; DELETE /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-052;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-053 | InternalExpertLookupTests.test_schema_has_four_fields_independent_scope_and_all_examples / sqlite接口 | lookup schema有独立expert:lookup/HMAC、两query、四字段及全部HTTP错误示例 | 本轮执行确认:lookup schema有独立expert:lookup/HMAC、两query、四字段及全部HTTP错误示例;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-053;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-054 | InternalExpertLookupTests.test_single_expert_double_phone_or_email_hit_is_not_ambiguous / sqlite接口 | 同一专家两个号码或邮箱同时命中仍唯一,不返回409 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-054;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-055 | InternalExpertLookupTests.test_whitelist_and_only_required_columns_loaded / sqlite接口 | lookup只加载Candidates.id/name,响应四字段且无电话邮箱背景费用等敏感值 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-055;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-056 | InternalUsersTests.test_default_only_active_and_whitelisted_fields / sqlite接口 | 员工查询默认仅激活账号及固定基本字段,不泄漏密码角色等 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-056;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-057 | InternalUsersTests.test_disabled_application_rejected / sqlite接口 | 停用应用查询员工返回401 | GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-057;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-058 | InternalUsersTests.test_email_is_exact_and_case_insensitive / sqlite接口 | 员工邮箱不区分大小写精确匹配,不作子串查询 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-058;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-059 | InternalUsersTests.test_existing_scopes_do_not_grant_user_directory / sqlite接口 | 其他既有Scope不能读取员工目录,返回403 | GET /internal/v1/users/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-059;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-060 | InternalUsersTests.test_explicit_inactive_and_inactive_hidden_by_default / sqlite接口 | 默认隐藏未激活员工,显式指定状态才返回 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-060;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-061 | InternalUsersTests.test_filters_combine_with_and / sqlite接口 | 员工多条件按AND组合,不放宽为OR | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-061;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-062 | InternalUsersTests.test_id_filter / sqlite接口 | 员工ID精确过滤,返回对应账号 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-062;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-063 | InternalUsersTests.test_invalid_query_returns_http_400 / sqlite接口 | 员工查询非法参数返回HTTP400,不包装成成功 | GET /internal/v1/users/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-063;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-064 | InternalUsersTests.test_name_matches_chinese_and_english / sqlite接口 | 员工中文与英文姓名筛选可匹配相应记录 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-064;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-065 | InternalUsersTests.test_no_credentials_rejected / sqlite接口 | 员工查询无凭据401 | GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-065;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-066 | InternalUsersTests.test_pagination_order_total_and_empty_page / sqlite接口 | 员工分页顺序/total/空页响应保持正确 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-066;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-067 | InternalUsersTests.test_read_only_route / sqlite接口 | 员工接口写方法405,不增加业务写路由 | POST /internal/v1/users/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-067;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-068 | InternalUsersTests.test_replay_rejected / sqlite接口 | 员工查询重复Nonce返回401 | GET /internal/v1/users/:HTTP200/code=200; GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-068;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-069 | InternalUsersTests.test_schema_preserves_envelope_parameters_and_security / sqlite接口 | 员工schema保持响应信封、参数和HMAC安全契约 | 本轮执行确认:员工schema保持响应信封、参数和HMAC安全契约;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-069;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-070 | InternalUsersTests.test_scope_is_available_to_application_management / sqlite接口 | 该既有接口的Scope可被应用管理表单显式选择 | 本轮执行确认:该既有接口的Scope可被应用管理表单显式选择;全部对应断言成立。 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-070;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-071 | InternalUsersTests.test_trailing_slash_optional_without_redirect / sqlite接口 | 员工接口无尾斜杠签名请求不重定向且查询成功 | GET /internal/v1/users:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-071;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-072 | InternalUsersTests.test_wrong_signature_rejected / sqlite接口 | 员工查询错误签名401 | GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-072;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-073 | MeetingApiTests.test_resolve_contact_and_ambiguity / sqlite接口 | 原resolve唯一身份可解析,重复匹配仍409不任选联系人 | POST /internal/v1/clients/resolve/:HTTP200/code=200; POST /internal/v1/clients/resolve/:HTTP409/code=AMBIGUOUS_CONTACT;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-073;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-074 | MeetingApiTests.test_resolve_contact_requires_new_auth_after_number_replacement / sqlite接口 | 客户号码替换后旧认证不可绕过重新认证要求,未重认证解析404 | POST /internal/v1/clients/resolve/:HTTP200/code=200; POST /internal/v1/clients/resolve/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-074;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-075 | FormalExpertContractTests.test_formal_internal_identity_and_exact_projection / sqlite接口 | 独立QA合成专家ID81001返回内部ID及恰好四字段,公司职位与同条履历一致 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-075;sqlite-r1.log;无缺陷 |
| EQ-QA-SQL-076 | FormalExpertContractTests.test_formal_lookup_scope_does_not_grant_public_expert_read / sqlite接口 | 独立QA应用仅expert:lookup可查lookup,但公开专家列表403,应用权限仍只有lookup | GET /internal/v1/experts/lookup/:HTTP200/code=200; GET /internal/v1/experts/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-sqlite-r1.json#EQ-QA-SQL-076;sqlite-r1.log;无缺陷 |
| EQ-QA-PG-001 | ApplicationAuthTests.test_canonical_query_sorts_keys_and_preserves_duplicates / pg接口 | 规范签名查询串按键值排序且保留重复键,不丢失签名输入 | 本轮执行确认:规范签名查询串按键值排序且保留重复键,不丢失签名输入;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-001;pg-r1.log;无缺陷 |
| EQ-QA-PG-002 | ApplicationAuthTests.test_canonical_query_uses_rfc3986_space_encoding / pg接口 | 规范查询串的空格使用%20,不以加号替代 | 本轮执行确认:规范查询串的空格使用%20,不以加号替代;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-002;pg-r1.log;无缺陷 |
| EQ-QA-PG-003 | ApplicationAuthTests.test_disallowed_ip_is_forbidden / pg接口 | 签名有效但来源IP不在白名单时返回403 | 本轮执行确认:签名有效但来源IP不在白名单时返回403;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-003;pg-r1.log;无缺陷 |
| EQ-QA-PG-004 | ApplicationAuthTests.test_expired_timestamp_is_rejected / pg接口 | 过期签名时间戳返回401 | 本轮执行确认:过期签名时间戳返回401;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-004;pg-r1.log;无缺陷 |
| EQ-QA-PG-005 | ApplicationAuthTests.test_invalid_forwarded_ip_is_not_persisted / pg接口 | 非法转发IP不被保存为应用最后使用IP | 本轮执行确认:非法转发IP不被保存为应用最后使用IP;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-005;pg-r1.log;无缺陷 |
| EQ-QA-PG-006 | ApplicationAuthTests.test_missing_scope_is_forbidden / pg接口 | 签名有效但缺少接口Scope时返回403 | 本轮执行确认:签名有效但缺少接口Scope时返回403;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-006;pg-r1.log;无缺陷 |
| EQ-QA-PG-007 | ApplicationAuthTests.test_reused_nonce_is_rejected / pg接口 | 同一Nonce首次成功,重放返回401 | 本轮执行确认:同一Nonce首次成功,重放返回401;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-007;pg-r1.log;无缺陷 |
| EQ-QA-PG-008 | ApplicationAuthTests.test_valid_signature_authenticates_application / pg接口 | 合法应用签名认证成功并返回应用身份 | 本轮执行确认:合法应用签名认证成功并返回应用身份;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-008;pg-r1.log;无缺陷 |
| EQ-QA-PG-009 | ApplicationAuthTests.test_wrong_signature_is_rejected / pg接口 | 错误签名返回401 | 本轮执行确认:错误签名返回401;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-009;pg-r1.log;无缺陷 |
| EQ-QA-PG-010 | ApplicationManagementTests.test_create_returns_secret_once_and_list_never_returns_it / pg接口 | 应用创建仅首次展示Secret,普通列表不返回Secret | 本轮执行确认:应用创建仅首次展示Secret,普通列表不返回Secret;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-010;pg-r1.log;无缺陷 |
| EQ-QA-PG-011 | ApplicationManagementTests.test_non_admin_cannot_manage_applications / pg接口 | 非管理员不能创建或管理应用凭据 | 本轮执行确认:非管理员不能创建或管理应用凭据;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-011;pg-r1.log;无缺陷 |
| EQ-QA-PG-012 | ApplicationManagementTests.test_rotate_secret_invalidates_previous_secret / pg接口 | 轮换Secret后旧签名失效,新Secret有效 | 本轮执行确认:轮换Secret后旧签名失效,新Secret有效;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-012;pg-r1.log;无缺陷 |
| EQ-QA-PG-013 | InternalClientsTests.test_deleted_contact_and_company_are_hidden / pg接口 | 联系人或公司删除后,ID和手机号查询均404 | GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-013;pg-r1.log;无缺陷 |
| EQ-QA-PG-014 | InternalClientsTests.test_deleted_duplicate_does_not_cause_ambiguity / pg接口 | 删除联系人、删除公司及无公司重复数据不触发歧义 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-014;pg-r1.log;无缺陷 |
| EQ-QA-PG-015 | InternalClientsTests.test_disabled_app_and_disallowed_ip / pg接口 | 停用应用401;恢复后不允许的IP403 | GET /internal/v1/clients/:HTTP401/code=authentication_failed; GET /internal/v1/clients/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-015;pg-r1.log;无缺陷 |
| EQ-QA-PG-016 | InternalClientsTests.test_id_lookup_whitelist / pg接口 | 联系人ID命中200且严格五字段,不返回联系方式或备注 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-016;pg-r1.log;无缺陷 |
| EQ-QA-PG-017 | InternalClientsTests.test_invalid_missing_combined_unknown_and_repeated_queries / pg接口 | 客户查询缺失、空、非法、组合、未知或重复参数均400/INVALID_REQUEST | GET /internal/v1/clients/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-017;pg-r1.log;无缺陷 |
| EQ-QA-PG-018 | InternalClientsTests.test_missing_contact_is_404 / pg接口 | 不存在的联系人ID返回404/CONTACT_NOT_FOUND | GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-018;pg-r1.log;无缺陷 |
| EQ-QA-PG-019 | InternalClientsTests.test_missing_credentials_bad_signature_and_replay / pg接口 | 缺凭据、错签和Nonce重放401,首次合法调用成功 | GET /internal/v1/clients/:HTTP401/code=authentication_failed; GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-019;pg-r1.log;无缺陷 |
| EQ-QA-PG-020 | InternalClientsTests.test_multiple_contacts_are_ambiguous_including_cross_field / pg接口 | 不同联系人跨主备用号重复时409且无data,改ID可查 | GET /internal/v1/clients/:HTTP409/code=AMBIGUOUS_CONTACT; GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-020;pg-r1.log;无缺陷 |
| EQ-QA-PG-021 | InternalClientsTests.test_no_company_is_hidden / pg接口 | 无公司客户联系人按ID和手机号均404 | GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-021;pg-r1.log;无缺陷 |
| EQ-QA-PG-022 | InternalClientsTests.test_no_write_methods_or_redirect / pg接口 | 客户查询支持无尾斜杠不重定向,写方法405且客户数据不变 | GET /internal/v1/clients:HTTP200/code=200; POST /internal/v1/clients/:HTTP405/code=method_not_allowed; PUT /internal/v1/clients/:HTTP405/code=method_not_allowed; PATCH /internal/v1/clients/:HTTP405/code=method_not_allowed; DELETE /internal/v1/clients/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-022;pg-r1.log;无缺陷 |
| EQ-QA-PG-023 | InternalClientsTests.test_null_ordinary_fields_are_retained / pg接口 | 客户普通姓名、公司名和职位null时仍保留固定字段 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-023;pg-r1.log;无缺陷 |
| EQ-QA-PG-024 | InternalClientsTests.test_other_scopes_do_not_grant_contact_read / pg接口 | client:resolve/user:read/expert:read等不授予client:read,返回403 | GET /internal/v1/clients/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-024;pg-r1.log;无缺陷 |
| EQ-QA-PG-025 | InternalClientsTests.test_primary_and_backup_phone_exact / pg接口 | 客户主备用号精确命中200,号码子串不命中404 | GET /internal/v1/clients/:HTTP200/code=200; GET /internal/v1/clients/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-025;pg-r1.log;无缺陷 |
| EQ-QA-PG-026 | InternalClientsTests.test_query_only_loads_projection_fields / pg接口 | 客户ORM仅实例化id/name/company_id/position等必要投影列 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-026;pg-r1.log;无缺陷 |
| EQ-QA-PG-027 | InternalClientsTests.test_resolve_route_is_unchanged / pg接口 | 原clients/resolve仍映射MeetingView的POST resolve_contact | 本轮执行确认:原clients/resolve仍映射MeetingView的POST resolve_contact;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-027;pg-r1.log;无缺陷 |
| EQ-QA-PG-028 | InternalClientsTests.test_same_record_matching_both_phones_is_unique / pg接口 | 同一客户主备用号均命中时只算一个联系人 | GET /internal/v1/clients/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-028;pg-r1.log;无缺陷 |
| EQ-QA-PG-029 | InternalClientsTests.test_schema_contract / pg接口 | 客户schema有HMAC、两参数、五字段及200/400/401/403/404/405/409示例 | 本轮执行确认:客户schema有HMAC、两参数、五字段及200/400/401/403/404/405/409示例;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-029;pg-r1.log;无缺陷 |
| EQ-QA-PG-030 | InternalClientsTests.test_scope_available_without_automatic_grant / pg接口 | client:read可显式选择,但既有client:resolve应用不自动扩权 | 本轮执行确认:client:read可显式选择,但既有client:resolve应用不自动扩权;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-030;pg-r1.log;无缺陷 |
| EQ-QA-PG-031 | InternalExpertLookupTests.test_all_null_dates_have_stable_id_tiebreak / pg接口 | 工作履历日期全部null时稳定选最大ID的同一行公司职位 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-031;pg-r1.log;无缺陷 |
| EQ-QA-PG-032 | InternalExpertLookupTests.test_auth_missing_bad_signature_tampering_and_replay / pg接口 | 专家lookup缺凭据、错签、签名后篡改查询及重放均401 | GET /internal/v1/experts/lookup/:HTTP401/code=authentication_failed; GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-032;pg-r1.log;无缺陷 |
| EQ-QA-PG-033 | InternalExpertLookupTests.test_deleted_and_null_deleted_experts_excluded / pg接口 | 专家is_deleted=true或null均排除,手机号/邮箱返回404 | GET /internal/v1/experts/lookup/:HTTP404/code=EXPERT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-033;pg-r1.log;无缺陷 |
| EQ-QA-PG-034 | InternalExpertLookupTests.test_deleted_duplicate_does_not_make_ambiguous / pg接口 | 已删除或null删除标志的重复专家不导致有效专家歧义 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-034;pg-r1.log;无缺陷 |
| EQ-QA-PG-035 | InternalExpertLookupTests.test_derivative_does_not_merge_by_original_id / pg接口 | 派生与原专家共用号码仍按不同Candidates.id判409,不按original_id合并 | GET /internal/v1/experts/lookup/:HTTP409/code=AMBIGUOUS_EXPERT;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-035;pg-r1.log;无缺陷 |
| EQ-QA-PG-036 | InternalExpertLookupTests.test_disabled_app_and_ip_restriction / pg接口 | 专家lookup停用应用401,IP不允许403 | GET /internal/v1/experts/lookup/:HTTP401/code=authentication_failed; GET /internal/v1/experts/lookup/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-036;pg-r1.log;无缺陷 |
| EQ-QA-PG-037 | InternalExpertLookupTests.test_exact_matching_and_no_phone_normalization / pg接口 | 手机号和邮箱不做子串匹配;手机号不拼区号,已存国际格式精确命中 | GET /internal/v1/experts/lookup/:HTTP404/code=EXPERT_NOT_FOUND; GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-037;pg-r1.log;无缺陷 |
| EQ-QA-PG-038 | InternalExpertLookupTests.test_galaxy_is_not_part_of_identity_domain / pg接口 | 只在Galaxy存在相同号码时lookup返回404,不混入Galaxy身份 | GET /internal/v1/experts/lookup/:HTTP404/code=EXPERT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-038;pg-r1.log;无缺陷 |
| EQ-QA-PG-039 | InternalExpertLookupTests.test_invalid_unknown_empty_repeated_or_combined_queries / pg接口 | lookup拒绝无条件、空、首尾空白、越长、坏邮箱、组合、重复及未知参数,均400 | GET /internal/v1/experts/lookup/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-039;pg-r1.log;无缺陷 |
| EQ-QA-PG-040 | InternalExpertLookupTests.test_latest_work_not_necessarily_current_employment / pg接口 | 取最近started_at的work履历,即使已离职也保持最近记录语义 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-040;pg-r1.log;无缺陷 |
| EQ-QA-PG-041 | InternalExpertLookupTests.test_multiple_expert_ids_email_ambiguous_ignore_case / pg接口 | 不同专家邮箱跨主备用且大小写相异重复时返回409 | GET /internal/v1/experts/lookup/:HTTP409/code=AMBIGUOUS_EXPERT;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-041;pg-r1.log;无缺陷 |
| EQ-QA-PG-042 | InternalExpertLookupTests.test_multiple_expert_ids_phone_ambiguous_no_candidate_list / pg接口 | 不同专家号码重复返回409/AMBIGUOUS_EXPERT,仅code/message且不泄漏候选 | GET /internal/v1/experts/lookup/:HTTP409/code=AMBIGUOUS_EXPERT;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-042;pg-r1.log;无缺陷 |
| EQ-QA-PG-043 | InternalExpertLookupTests.test_no_ai_gate_source_lock_availability_or_derivative_filter / pg接口 | Candidates各source、锁定、不可约及派生记录均可查,不要求AI公开许可 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-043;pg-r1.log;无缺陷 |
| EQ-QA-PG-044 | InternalExpertLookupTests.test_no_work_experience_fields_are_null / pg接口 | 无工作履历时四字段保留,公司和职位均null | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-044;pg-r1.log;无缺陷 |
| EQ-QA-PG-045 | InternalExpertLookupTests.test_non_work_deleted_null_deleted_experiences_are_ignored / pg接口 | 教育/项目、已删和null删除标志履历不覆盖有效work记录 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-045;pg-r1.log;无缺陷 |
| EQ-QA-PG-046 | InternalExpertLookupTests.test_null_and_blank_values_stay_on_same_row / pg接口 | 姓名null、最近履历公司null/职位空串原样保留,不跨行补旧值 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-046;pg-r1.log;无缺陷 |
| EQ-QA-PG-047 | InternalExpertLookupTests.test_null_dates_sort_last_and_ties_use_highest_id / pg接口 | 履历日期DESC NULLS LAST,同日起点取最大ID,两个输出来自同一行 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-047;pg-r1.log;无缺陷 |
| EQ-QA-PG-048 | InternalExpertLookupTests.test_original_routes_and_new_anchor_do_not_conflict / pg接口 | 新lookup、原公开列表/数字详情和clients/resolve路由保持,额外尾路径不匹配 | 本轮执行确认:新lookup、原公开列表/数字详情和clients/resolve路由保持,额外尾路径不匹配;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-048;pg-r1.log;无缺陷 |
| EQ-QA-PG-049 | InternalExpertLookupTests.test_other_scopes_are_insufficient_and_no_automatic_grant / pg接口 | expert:read/client:read/user:read等不授予lookup;缺expert:lookup403且不自动增权 | GET /internal/v1/experts/lookup/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-049;pg-r1.log;无缺陷 |
| EQ-QA-PG-050 | InternalExpertLookupTests.test_primary_and_backup_email_ignore_case / pg接口 | 专家主备用邮箱不区分大小写精确命中200且内部专家ID正确 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-050;pg-r1.log;无缺陷 |
| EQ-QA-PG-051 | InternalExpertLookupTests.test_primary_and_backup_phone / pg接口 | 专家主备用手机号均命中200,四字段姓名公司职位与合成记录一致 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-051;pg-r1.log;无缺陷 |
| EQ-QA-PG-052 | InternalExpertLookupTests.test_read_only_methods_and_optional_slash / pg接口 | lookup支持无尾斜杠,POST/PUT/PATCH/DELETE405且专家/履历不变 | GET /internal/v1/experts/lookup:HTTP200/code=200; POST /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed; PUT /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed; PATCH /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed; DELETE /internal/v1/experts/lookup/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-052;pg-r1.log;无缺陷 |
| EQ-QA-PG-053 | InternalExpertLookupTests.test_schema_has_four_fields_independent_scope_and_all_examples / pg接口 | lookup schema有独立expert:lookup/HMAC、两query、四字段及全部HTTP错误示例 | 本轮执行确认:lookup schema有独立expert:lookup/HMAC、两query、四字段及全部HTTP错误示例;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-053;pg-r1.log;无缺陷 |
| EQ-QA-PG-054 | InternalExpertLookupTests.test_single_expert_double_phone_or_email_hit_is_not_ambiguous / pg接口 | 同一专家两个号码或邮箱同时命中仍唯一,不返回409 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-054;pg-r1.log;无缺陷 |
| EQ-QA-PG-055 | InternalExpertLookupTests.test_whitelist_and_only_required_columns_loaded / pg接口 | lookup只加载Candidates.id/name,响应四字段且无电话邮箱背景费用等敏感值 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-055;pg-r1.log;无缺陷 |
| EQ-QA-PG-056 | InternalUsersTests.test_default_only_active_and_whitelisted_fields / pg接口 | 员工查询默认仅激活账号及固定基本字段,不泄漏密码角色等 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-056;pg-r1.log;无缺陷 |
| EQ-QA-PG-057 | InternalUsersTests.test_disabled_application_rejected / pg接口 | 停用应用查询员工返回401 | GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-057;pg-r1.log;无缺陷 |
| EQ-QA-PG-058 | InternalUsersTests.test_email_is_exact_and_case_insensitive / pg接口 | 员工邮箱不区分大小写精确匹配,不作子串查询 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-058;pg-r1.log;无缺陷 |
| EQ-QA-PG-059 | InternalUsersTests.test_existing_scopes_do_not_grant_user_directory / pg接口 | 其他既有Scope不能读取员工目录,返回403 | GET /internal/v1/users/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-059;pg-r1.log;无缺陷 |
| EQ-QA-PG-060 | InternalUsersTests.test_explicit_inactive_and_inactive_hidden_by_default / pg接口 | 默认隐藏未激活员工,显式指定状态才返回 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-060;pg-r1.log;无缺陷 |
| EQ-QA-PG-061 | InternalUsersTests.test_filters_combine_with_and / pg接口 | 员工多条件按AND组合,不放宽为OR | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-061;pg-r1.log;无缺陷 |
| EQ-QA-PG-062 | InternalUsersTests.test_id_filter / pg接口 | 员工ID精确过滤,返回对应账号 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-062;pg-r1.log;无缺陷 |
| EQ-QA-PG-063 | InternalUsersTests.test_invalid_query_returns_http_400 / pg接口 | 员工查询非法参数返回HTTP400,不包装成成功 | GET /internal/v1/users/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-063;pg-r1.log;无缺陷 |
| EQ-QA-PG-064 | InternalUsersTests.test_name_matches_chinese_and_english / pg接口 | 员工中文与英文姓名筛选可匹配相应记录 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-064;pg-r1.log;无缺陷 |
| EQ-QA-PG-065 | InternalUsersTests.test_no_credentials_rejected / pg接口 | 员工查询无凭据401 | GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-065;pg-r1.log;无缺陷 |
| EQ-QA-PG-066 | InternalUsersTests.test_pagination_order_total_and_empty_page / pg接口 | 员工分页顺序/total/空页响应保持正确 | GET /internal/v1/users/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-066;pg-r1.log;无缺陷 |
| EQ-QA-PG-067 | InternalUsersTests.test_read_only_route / pg接口 | 员工接口写方法405,不增加业务写路由 | POST /internal/v1/users/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-067;pg-r1.log;无缺陷 |
| EQ-QA-PG-068 | InternalUsersTests.test_replay_rejected / pg接口 | 员工查询重复Nonce返回401 | GET /internal/v1/users/:HTTP200/code=200; GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-068;pg-r1.log;无缺陷 |
| EQ-QA-PG-069 | InternalUsersTests.test_schema_preserves_envelope_parameters_and_security / pg接口 | 员工schema保持响应信封、参数和HMAC安全契约 | 本轮执行确认:员工schema保持响应信封、参数和HMAC安全契约;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-069;pg-r1.log;无缺陷 |
| EQ-QA-PG-070 | InternalUsersTests.test_scope_is_available_to_application_management / pg接口 | 该既有接口的Scope可被应用管理表单显式选择 | 本轮执行确认:该既有接口的Scope可被应用管理表单显式选择;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-070;pg-r1.log;无缺陷 |
| EQ-QA-PG-071 | InternalUsersTests.test_trailing_slash_optional_without_redirect / pg接口 | 员工接口无尾斜杠签名请求不重定向且查询成功 | GET /internal/v1/users:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-071;pg-r1.log;无缺陷 |
| EQ-QA-PG-072 | InternalUsersTests.test_wrong_signature_rejected / pg接口 | 员工查询错误签名401 | GET /internal/v1/users/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-072;pg-r1.log;无缺陷 |
| EQ-QA-PG-073 | MeetingApiTests.test_resolve_contact_and_ambiguity / pg接口 | 原resolve唯一身份可解析,重复匹配仍409不任选联系人 | POST /internal/v1/clients/resolve/:HTTP200/code=200; POST /internal/v1/clients/resolve/:HTTP409/code=AMBIGUOUS_CONTACT;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-073;pg-r1.log;无缺陷 |
| EQ-QA-PG-074 | MeetingApiTests.test_resolve_contact_requires_new_auth_after_number_replacement / pg接口 | 客户号码替换后旧认证不可绕过重新认证要求,未重认证解析404 | POST /internal/v1/clients/resolve/:HTTP200/code=200; POST /internal/v1/clients/resolve/:HTTP404/code=CONTACT_NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-074;pg-r1.log;无缺陷 |
| EQ-QA-PG-075 | FormalExpertContractTests.test_formal_internal_identity_and_exact_projection / pg接口 | 独立QA合成专家ID81001返回内部ID及恰好四字段,公司职位与同条履历一致 | GET /internal/v1/experts/lookup/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-075;pg-r1.log;无缺陷 |
| EQ-QA-PG-076 | FormalExpertContractTests.test_formal_lookup_scope_does_not_grant_public_expert_read / pg接口 | 独立QA应用仅expert:lookup可查lookup,但公开专家列表403,应用权限仍只有lookup | GET /internal/v1/experts/lookup/:HTTP200/code=200; GET /internal/v1/experts/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-076;pg-r1.log;无缺陷 |
| EQ-QA-PG-077 | InternalExpertsTests.test_ai_only_does_not_enable_wechat_and_revocation_is_immediate / pg接口 | AI单独许可不打开微信;移除AI后公开API立即404且微信许可独立 | GET /internal/v1/experts/1/:HTTP404/code=NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-077;pg-r1.log;无缺陷 |
| EQ-QA-PG-078 | InternalExpertsTests.test_api_is_read_only / pg接口 | 原公开专家列表/详情写方法均405 | POST /internal/v1/experts/:HTTP405/code=method_not_allowed; POST /internal/v1/experts/2/:HTTP405/code=method_not_allowed; PUT /internal/v1/experts/:HTTP405/code=method_not_allowed; PUT /internal/v1/experts/2/:HTTP405/code=method_not_allowed; PATCH /internal/v1/experts/:HTTP405/code=method_not_allowed; PATCH /internal/v1/experts/2/:HTTP405/code=method_not_allowed; DELETE /internal/v1/experts/:HTTP405/code=method_not_allowed; DELETE /internal/v1/experts/2/:HTTP405/code=method_not_allowed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-078;pg-r1.log;无缺陷 |
| EQ-QA-PG-079 | InternalExpertsTests.test_authentication_and_dedicated_scope_are_required / pg接口 | 原公开专家缺凭据401,无expert:read的已认证应用403 | GET /internal/v1/experts/:HTTP401/code=authentication_failed; GET /internal/v1/experts/:HTTP403/code=permission_denied; GET /internal/v1/experts/3/:HTTP403/code=permission_denied;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-079;pg-r1.log;无缺陷 |
| EQ-QA-PG-080 | InternalExpertsTests.test_draft_archived_future_null_date_and_deleted_are_hidden / pg接口 | 草稿、归档、未来或null发布时间、已删除专家均不出现在原公开列表/详情 | GET /internal/v1/experts/:HTTP200/code=200; GET /internal/v1/experts/4/:HTTP404/code=NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-080;pg-r1.log;无缺陷 |
| EQ-QA-PG-081 | InternalExpertsTests.test_invalid_query_is_rejected / pg接口 | 原公开API非法页码/页大小/未知平台参数400/INVALID_REQUEST | GET /internal/v1/experts/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-081;pg-r1.log;无缺陷 |
| EQ-QA-PG-082 | InternalExpertsTests.test_keyword_and_pagination_only_search_public_fields / pg接口 | 原公开搜索只检索公开字段,分页total/顺序和越界空页正确 | GET /internal/v1/experts/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-082;pg-r1.log;无缺陷 |
| EQ-QA-PG-083 | InternalExpertsTests.test_openapi_documents_list_detail_and_scope / pg接口 | 完整schema仍保留公开专家列表、详情及expert:read说明 | 本轮执行确认:完整schema仍保留公开专家列表、详情及expert:read说明;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-083;pg-r1.log;无缺陷 |
| EQ-QA-PG-084 | InternalExpertsTests.test_other_source_profiles_cannot_be_read_or_selected / pg接口 | 其他来源公开资料不可读取,客户端不能选择application_id来源 | GET /internal/v1/experts/:HTTP200/code=200; GET /internal/v1/experts/10/:HTTP404/code=NOT_FOUND; GET /internal/v1/experts/:HTTP400/code=INVALID_REQUEST;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-084;pg-r1.log;无缺陷 |
| EQ-QA-PG-085 | InternalExpertsTests.test_scope_is_available_to_application_management / pg接口 | 该既有接口的Scope可被应用管理表单显式选择 | 本轮执行确认:该既有接口的Scope可被应用管理表单显式选择;全部对应断言成立。 | Pass | cases-pg-r1.json#EQ-QA-PG-085;pg-r1.log;无缺陷 |
| EQ-QA-PG-086 | InternalExpertsTests.test_shared_public_source_and_whitelisted_projection / pg接口 | 原公开列表/详情仍来自服务端绑定源,固定公开字段无内部姓名/联系方式泄漏 | GET /internal/v1/experts/:HTTP200/code=200; GET /internal/v1/experts/12/:HTTP200/code=200;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-086;pg-r1.log;无缺陷 |
| EQ-QA-PG-087 | InternalExpertsTests.test_signature_tampering_and_nonce_reuse_are_rejected / pg接口 | 原公开API错误签名与重复Nonce均拒绝401 | GET /internal/v1/experts/:HTTP200/code=200; GET /internal/v1/experts/:HTTP401/code=authentication_failed;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-087;pg-r1.log;无缺陷 |
| EQ-QA-PG-088 | InternalExpertsTests.test_unavailable_source_fails_closed / pg接口 | 公开源缺失或停用时503,不回退其他来源 | GET /internal/v1/experts/:HTTP503/code=MEETING_APPLICATION_NOT_FOUND; GET /internal/v1/experts/:HTTP503/code=MEETING_APPLICATION_UNAVAILABLE;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-088;pg-r1.log;无缺陷 |
| EQ-QA-PG-089 | InternalExpertsTests.test_wechat_only_profile_is_not_readable_by_ai / pg接口 | 仅微信公开的专家不出现在AI列表,AI详情404且微信仍可见 | GET /internal/v1/experts/:HTTP200/code=200; GET /internal/v1/experts/15/:HTTP404/code=NOT_FOUND;对应数据、权限或排序断言全部成立 | Pass | cases-pg-r1.json#EQ-QA-PG-089;pg-r1.log;无缺陷 |
| EQ-QA-DOC-001 | API文字说明核对 / 文档接口 | 路由、HMAC和独立expert:lookup、两条件互斥、精确匹配、四字段/内部ID、同条最近work及null顺序、HTTP错误、非身份认证和未发布边界说明准确 | 本轮合成接口调用与说明一致:200四字段;无凭据/错签/重放401、缺Scope403、参数400、无匹配404、歧义409及写方法405均由相应用例确认;NULLS LAST/-id和同条null/空串符合文字说明。文档明确开发候选未发布,不把读取当身份认证;未验证外部ndb_client.py或远端HMAC脚本 | Pass | doc-review.json;无缺陷 |
文字接入说明和手册适用性¶
本轮合成接口调用与说明一致:200四字段;无凭据/错签/重放401、缺Scope403、参数400、无匹配404、歧义409及写方法405均由相应用例确认;NULLS LAST/-id和同条null/空串符合文字说明。文档明确开发候选未发布,不把读取当身份认证;未验证外部ndb_client.py或远端HMAC脚本。本轮无直接用户界面,按用户本轮明确边界不采浏览器截图,API说明代替截图手册;主线程在交付中说明。不冒称外部SDK/Apifox或UI视觉复核已执行。
风险与未验证项¶
- 正式QA结论仅对上述哈希的隔离环境API契约有效,不表示commit/push/deploy、生产验证或远端Apifox已完成。
- 无真实数据或真实AK/SK查询,无生产规模执行计划/性能、并发一致性、网关配额及日志脱敏验证;未验证真实PostgreSQL迁移历史(本轮禁用migrations)。
- 全Candidates全局读取、包含锁定/不可约/hw/派生是批准契约,不是AI公开许可或联系方式持有人认证。Scope授予须另行明确,不自动扩权。
- AOCI既有治理漂移未处理,无业务/版本/config变动。原config SHA256 2ddd08eb2eb9245bfa9dfac0e166de60030486735747b5bcd0516b37ed34c1ee;6文件哈希前后相同。
- 本轮自建容器ndb-eq-formal-qa-20261019-01a0ba71及其匿名卷已按ID/标签核验清理,其他容器未触碰。
下一步¶
仅待Redmine本journal写入后重新读取确认标题、166条编号、汇总、证据;成功后QA交付完成。业务实现/发布授权仍由主线程另行处理,不从本QA结果推导发布权限。
RA Updated by Redmine Admin 23 days ago Actions #5
QA 真实测试环境 HMAC 签名验收 - 2026-10-19¶
- 项目NDB,需求#9;独立QA web_qa。
- 环境:https://tcrm-api.mindsetech.com;Operations确认运行Backend1.20.4b0,本轮真实签名调用不是匿名401或隔离服务。
- 身份:本轮用户明确授权新建的测试应用ID2,仅expert:lookup,精确本机出口/32,短期有效;凭据仅BW与受控内存,报告不含AK/SK/签名/请求头。
- 数据:只查询本任务合成专家574234,邮箱example.invalid、全零合成号、QA公司职位;未查询真实专家。
- 汇总:Pass17 / Fail0 / Blocked0 / Skipped0(仅下列本轮已执行范围)。
- 证据:outputs/candidate-attachments-20261019/staging/lookup-live-results.json;lookup-live.mjs与lookup-scope-check.mjs只从BW读本任务凭据,不含秘密。
| 编号 | 用例 | 层级 | 预期 | 实际 | 结果 | 证据 |
|---|---|---|---|---|---|---|
| LOOKUP-LIVE-001 | 合成邮箱精确查询四字段 | 部署测试服务接口 | 200 | {"http": 200, "code": 200, "message": null, "data": {"expert_id": 574234, "name": "QA附件验收20261019", "company": "QA合成公司", "position": "QA验证专员"}, "keys": ["company", "expert_id", "name", "position"]} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-002 | 合成邮箱大小写不敏感 | 部署测试服务接口 | 200 | {"http": 200, "code": 200, "message": null, "data": {"expert_id": 574234, "name": "QA附件验收20261019", "company": "QA合成公司", "position": "QA验证专员"}, "keys": ["company", "expert_id", "name", "position"]} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-003 | 合成主号码精确查询 | 部署测试服务接口 | 200 | {"http": 200, "code": 200, "message": null, "data": {"expert_id": 574234, "name": "QA附件验收20261019", "company": "QA合成公司", "position": "QA验证专员"}, "keys": ["company", "expert_id", "name", "position"]} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-004 | 保留域合成邮箱无匹配 | 部署测试服务接口 | 404 | {"http": 404, "code": "EXPERT_NOT_FOUND", "message": "未找到匹配的专家"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-005 | 缺少查询参数 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "[ErrorDetail(string='必须提供单个查询条件,且不支持未知或重复参数', code='invalid')]"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-006 | 同时phone/email拒绝 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "[ErrorDetail(string='必须提供单个查询条件,且不支持未知或重复参数', code='invalid')]"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-007 | 重复同名参数拒绝 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "[ErrorDetail(string='必须提供单个查询条件,且不支持未知或重复参数', code='invalid')]"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-008 | 空参数拒绝 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "{'non_field_errors': [ErrorDetail(string='phone 与 email 必须且只能提供一个', code='invalid')]}"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-009 | 未知参数拒绝 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "[ErrorDetail(string='必须提供单个查询条件,且不支持未知或重复参数', code='invalid')]"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-010 | 首尾空白拒绝 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "{'email': [ErrorDetail(string='Enter a valid email address.', code='invalid')]}"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-011 | 邮箱格式拒绝 | 部署测试服务接口 | 400 | {"http": 400, "code": "INVALID_REQUEST", "message": "{'email': [ErrorDetail(string='Enter a valid email address.', code='invalid')]}"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-012 | 写方法拒绝 | 部署测试服务接口 | 405 | {"http": 405, "code": "method_not_allowed", "message": "Method "POST" not allowed."} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-013 | 错误签名拒绝 | 部署测试服务接口 | 401 | {"http": 401, "code": "authentication_failed", "message": "应用签名校验失败。"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-014 | 过期签名拒绝 | 部署测试服务接口 | 401 | {"http": 401, "code": "authentication_failed", "message": "应用鉴权请求已过期。"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-015 | 无尾斜杠合法查询 | 部署测试服务接口 | 200 | {"http": 200, "code": 200, "message": null, "data": {"expert_id": 574234, "name": "QA附件验收20261019", "company": "QA合成公司", "position": "QA验证专员"}, "keys": ["company", "expert_id", "name", "position"]} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-016 | Nonce重放拒绝 | 部署测试服务接口 | 首次200,重复401 | {"first": 200, "replayed": 401, "code": "authentication_failed"} | Pass | lookup-live-results.json |
| LOOKUP-LIVE-017 | lookup应用不继承expert:read权限 | 部署测试服务接口 | 403 | {"http": 403, "code": "permission_denied", "message": "应用缺少 Scope:expert:read"} | Pass | lookup-live-results.json |
接入说明核验¶
phone/email二选一;邮箱不区分大小写;使用最终发送URL生成HMAC,空请求体SHA256、Unix秒时间戳、新Nonce;成功数据严格只有expert_id/name/company/position,真实合成履历值与CRM一致。普通expert:read没有自动授予本次应用;访问既有专家公开详情实际403。错误和写方法不返回专家资料。
未执行和收尾¶
备用号码/邮箱、多个专家冲突409、删除标志/跨source/派生及空履历组合未在共享测试环境新增额外数据验证,这些仍是已有隔离测试证据,不能当本轮运行结果。未修改既有BFF应用、真实用户角色或生产。测试应用验收后停用尚在串行收尾中,稍后单独追加状态读回;短期过期时间和白名单保持不放宽。
RA Updated by Redmine Admin 23 days ago Actions #6
QA 测试应用停用收尾 - 2026-10-19¶
应用ID2“QA expert lookup 20261019”已按用户授权,经真实测试CRM应用管理UI改为disabled。PUT /v1/api-applications/2 HTTP200/code200;随后真实应用列表GET读回同ID状态disabled。唯一expert:lookup、原精确出口/32、原短期到期均保留。没有修改或停用BFF/其他应用,没有重置密钥或扩大Scope。Secret仍仅BW存储,记录不含凭据。
| 编号 | 用例 | 层级 | 预期 | 实际 | 结果 | 证据 |
|---|---|---|---|---|---|---|
| LOOKUP-CLEANUP-001 | 仅停用本任务临时应用并读回 | 真实测试管理UI/API | 应用2 disabled且其余配置不扩大 | PUT200/code200,GET同ID disabled,scopes仍仅expert:lookup | Pass | outputs/candidate-attachments-20261019/staging/test-application-disabled.json |
本次状态读回证明停用落库;未再对停用后的凭据发起运行态调用,不把它描述为额外401验收。之前17条真实签名结果保留。