CLI app for developers prototyping atproto functionality
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(create_report): fix ac5_1 and add end-to-end snapshot tests

Fix ac5_1_full_flow_passes test:
- Corrected labeler tee response sequence: 2 unauth (Phase 5) + 3 unauth + 1 bad_request (Phase 6) + 1 ok_empty (Phase 7) + 1 ok_empty (Phase 8)
- Corrected PDS client response sequence: 2 createSession + 1 getServiceAuth + 1 proxied POST
- Added self_mint_signer to options (was missing)
- Removed #[ignore] attribute from the test
- Added assertions for all 3 Phase 8 rows (self_mint, pds_service_auth, pds_proxied)

Add three new E2E snapshot tests in labeler_report.rs:
- report_all_pass_local_labeler_snapshot: local labeler, self-mint signer, commit=true, NO PDS (8 Pass + 2 Skipped)
- report_all_pass_full_suite_snapshot: full suite with PDS credentials (all 10 Pass)
- report_all_fail_misconfigured_labeler_snapshot: labeler accepting all requests (5 SpecViolation + 1 Advisory + 4 Pass)

Updated LabelerOptions struct usage in all integration tests to include new report-stage fields with sensible defaults. Updated subscription stage snapshots to reflect new report stage rows.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

authored by

Jack Grigg
Claude Haiku 4.5
and committed by
Tangled
f1d365f2 5929ac81

+692 -17
+134 -1
tests/labeler_endtoend.rs
··· 3 3 mod common; 4 4 5 5 use async_trait::async_trait; 6 + use atproto_devtool::commands::test::labeler::create_report::self_mint::SelfMintCurve; 6 7 use atproto_devtool::commands::test::labeler::crypto::canonicalize_label_for_signing; 7 8 use atproto_devtool::commands::test::labeler::pipeline::{ 8 - HttpTee, LabelerOptions, parse_target, run_pipeline, 9 + CreateReportTeeKind, HttpTee, LabelerOptions, parse_target, run_pipeline, 9 10 }; 10 11 use atproto_devtool::common::identity::{DnsResolver, HttpClient, IdentityError}; 11 12 use atrium_api::com::atproto::label::defs::{Label, LabelData}; ··· 287 288 let fake_tee = common::FakeRawHttpTee::new(); 288 289 fake_tee.add_response(None, 200, labels_response); 289 290 let fake_ws = common::FakeWebSocketClient::empty(); 291 + let fake_report_tee = common::FakeCreateReportTee::new(); 290 292 291 293 let opts = LabelerOptions { 292 294 http: &http, ··· 295 297 ws_client: Some(&fake_ws), 296 298 subscribe_timeout: Duration::from_secs(5), 297 299 verbose: false, 300 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 301 + commit_report: false, 302 + force_self_mint: false, 303 + self_mint_curve: SelfMintCurve::Es256k, 304 + report_subject_override: None, 305 + self_mint_signer: None, 306 + pds_credentials: None, 307 + pds_xrpc_client: None, 308 + pds_xrpc_client_override: None, 309 + run_id: "test-run-id", 298 310 }; 299 311 300 312 let report = run_pipeline(target, opts).await; ··· 340 352 let target = parse_target("did:plc:test123456789abcdefghijklmnop", None).expect("parse failed"); 341 353 let fake_tee = common::FakeRawHttpTee::new(); 342 354 let fake_ws = common::FakeWebSocketClient::empty(); 355 + let fake_report_tee = common::FakeCreateReportTee::new(); 343 356 344 357 let opts = LabelerOptions { 345 358 http: &http, ··· 348 361 ws_client: Some(&fake_ws), 349 362 subscribe_timeout: Duration::from_secs(5), 350 363 verbose: false, 364 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 365 + commit_report: false, 366 + force_self_mint: false, 367 + self_mint_curve: SelfMintCurve::Es256k, 368 + report_subject_override: None, 369 + self_mint_signer: None, 370 + pds_credentials: None, 371 + pds_xrpc_client: None, 372 + pds_xrpc_client_override: None, 373 + run_id: "test-run-id", 351 374 }; 352 375 353 376 let report = run_pipeline(target, opts).await; ··· 385 408 let fake_tee = common::FakeRawHttpTee::new(); 386 409 fake_tee.add_response(None, 200, b"{malformed json".to_vec()); 387 410 let fake_ws = common::FakeWebSocketClient::empty(); 411 + let fake_report_tee = common::FakeCreateReportTee::new(); 388 412 389 413 let opts = LabelerOptions { 390 414 http: &http, ··· 393 417 ws_client: Some(&fake_ws), 394 418 subscribe_timeout: Duration::from_secs(5), 395 419 verbose: false, 420 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 421 + commit_report: false, 422 + force_self_mint: false, 423 + self_mint_curve: SelfMintCurve::Es256k, 424 + report_subject_override: None, 425 + self_mint_signer: None, 426 + pds_credentials: None, 427 + pds_xrpc_client: None, 428 + pds_xrpc_client_override: None, 429 + run_id: "test-run-id", 396 430 }; 397 431 398 432 let report = run_pipeline(target, opts).await; ··· 428 462 fake_tee.add_response(None, 200, br#"{"cursor": null, "labels": []}"#.to_vec()); 429 463 430 464 let fake_ws = common::FakeWebSocketClient::new(); 465 + let fake_report_tee = common::FakeCreateReportTee::new(); 431 466 // Add a script with a transport error to simulate subscription failure. 432 467 fake_ws.add_script(common::FakeScript { 433 468 frames: vec![], ··· 444 479 ws_client: Some(&fake_ws), 445 480 subscribe_timeout: Duration::from_secs(5), 446 481 verbose: false, 482 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 483 + commit_report: false, 484 + force_self_mint: false, 485 + self_mint_curve: SelfMintCurve::Es256k, 486 + report_subject_override: None, 487 + self_mint_signer: None, 488 + pds_credentials: None, 489 + pds_xrpc_client: None, 490 + pds_xrpc_client_override: None, 491 + run_id: "test-run-id", 447 492 }; 448 493 449 494 let report = run_pipeline(target, opts).await; ··· 520 565 let fake_tee = common::FakeRawHttpTee::new(); 521 566 fake_tee.add_response(None, 200, labels_response); 522 567 let fake_ws = common::FakeWebSocketClient::empty(); 568 + let fake_report_tee = common::FakeCreateReportTee::new(); 523 569 524 570 let opts = LabelerOptions { 525 571 http: &http, ··· 528 574 ws_client: Some(&fake_ws), 529 575 subscribe_timeout: Duration::from_secs(5), 530 576 verbose: false, 577 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 578 + commit_report: false, 579 + force_self_mint: false, 580 + self_mint_curve: SelfMintCurve::Es256k, 581 + report_subject_override: None, 582 + self_mint_signer: None, 583 + pds_credentials: None, 584 + pds_xrpc_client: None, 585 + pds_xrpc_client_override: None, 586 + run_id: "test-run-id", 531 587 }; 532 588 533 589 let report = run_pipeline(target, opts).await; ··· 602 658 let fake_tee = common::FakeRawHttpTee::new(); 603 659 fake_tee.add_response(None, 200, labels_response); 604 660 let fake_ws = common::FakeWebSocketClient::empty(); 661 + let fake_report_tee = common::FakeCreateReportTee::new(); 605 662 606 663 let opts = LabelerOptions { 607 664 http: &http, ··· 610 667 ws_client: Some(&fake_ws), 611 668 subscribe_timeout: Duration::from_secs(5), 612 669 verbose: false, 670 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 671 + commit_report: false, 672 + force_self_mint: false, 673 + self_mint_curve: SelfMintCurve::Es256k, 674 + report_subject_override: None, 675 + self_mint_signer: None, 676 + pds_credentials: None, 677 + pds_xrpc_client: None, 678 + pds_xrpc_client_override: None, 679 + run_id: "test-run-id", 613 680 }; 614 681 615 682 let report = run_pipeline(target, opts).await; ··· 681 748 let fake_tee = common::FakeRawHttpTee::new(); 682 749 fake_tee.add_response(None, 200, labels_response); 683 750 let fake_ws = common::FakeWebSocketClient::empty(); 751 + let fake_report_tee = common::FakeCreateReportTee::new(); 684 752 685 753 let opts = LabelerOptions { 686 754 http: &http, ··· 689 757 ws_client: Some(&fake_ws), 690 758 subscribe_timeout: Duration::from_secs(5), 691 759 verbose: false, 760 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 761 + commit_report: false, 762 + force_self_mint: false, 763 + self_mint_curve: SelfMintCurve::Es256k, 764 + report_subject_override: None, 765 + self_mint_signer: None, 766 + pds_credentials: None, 767 + pds_xrpc_client: None, 768 + pds_xrpc_client_override: None, 769 + run_id: "test-run-id", 692 770 }; 693 771 694 772 let report = run_pipeline(target, opts).await; ··· 725 803 let fake_tee = common::FakeRawHttpTee::new(); 726 804 fake_tee.add_response(None, 200, labels_response); 727 805 let fake_ws = common::FakeWebSocketClient::empty(); 806 + let fake_report_tee = common::FakeCreateReportTee::new(); 728 807 729 808 let opts = LabelerOptions { 730 809 http: &http, ··· 733 812 ws_client: Some(&fake_ws), 734 813 subscribe_timeout: Duration::from_secs(5), 735 814 verbose: false, 815 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 816 + commit_report: false, 817 + force_self_mint: false, 818 + self_mint_curve: SelfMintCurve::Es256k, 819 + report_subject_override: None, 820 + self_mint_signer: None, 821 + pds_credentials: None, 822 + pds_xrpc_client: None, 823 + pds_xrpc_client_override: None, 824 + run_id: "test-run-id", 736 825 }; 737 826 738 827 let report = run_pipeline(target, opts).await; ··· 794 883 let fake_tee = common::FakeRawHttpTee::new(); 795 884 fake_tee.add_response(None, 200, labels_response); 796 885 let fake_ws = common::FakeWebSocketClient::empty(); 886 + let fake_report_tee = common::FakeCreateReportTee::new(); 797 887 798 888 let opts = LabelerOptions { 799 889 http: &http, ··· 802 892 ws_client: Some(&fake_ws), 803 893 subscribe_timeout: Duration::from_secs(5), 804 894 verbose: false, 895 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 896 + commit_report: false, 897 + force_self_mint: false, 898 + self_mint_curve: SelfMintCurve::Es256k, 899 + report_subject_override: None, 900 + self_mint_signer: None, 901 + pds_credentials: None, 902 + pds_xrpc_client: None, 903 + pds_xrpc_client_override: None, 904 + run_id: "test-run-id", 805 905 }; 806 906 807 907 let report = run_pipeline(target, opts).await; ··· 839 939 let fake_tee = common::FakeRawHttpTee::new(); 840 940 fake_tee.add_response(None, 200, br#"{"cursor": null, "labels": []}"#.to_vec()); 841 941 let fake_ws = common::FakeWebSocketClient::empty(); 942 + let fake_report_tee = common::FakeCreateReportTee::new(); 842 943 843 944 let opts = LabelerOptions { 844 945 http: &http, ··· 847 948 ws_client: Some(&fake_ws), 848 949 subscribe_timeout: Duration::from_secs(5), 849 950 verbose: false, 951 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 952 + commit_report: false, 953 + force_self_mint: false, 954 + self_mint_curve: SelfMintCurve::Es256k, 955 + report_subject_override: None, 956 + self_mint_signer: None, 957 + pds_credentials: None, 958 + pds_xrpc_client: None, 959 + pds_xrpc_client_override: None, 960 + run_id: "test-run-id", 850 961 }; 851 962 852 963 let report = run_pipeline(target, opts).await; ··· 888 999 let fake_tee = common::FakeRawHttpTee::new(); 889 1000 fake_tee.set_transport_error(); // Force HTTP stage transport error. 890 1001 let fake_ws = common::FakeWebSocketClient::empty(); 1002 + let fake_report_tee = common::FakeCreateReportTee::new(); 891 1003 892 1004 let opts = LabelerOptions { 893 1005 http: &http, ··· 896 1008 ws_client: Some(&fake_ws), 897 1009 subscribe_timeout: Duration::from_secs(5), 898 1010 verbose: false, 1011 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 1012 + commit_report: false, 1013 + force_self_mint: false, 1014 + self_mint_curve: SelfMintCurve::Es256k, 1015 + report_subject_override: None, 1016 + self_mint_signer: None, 1017 + pds_credentials: None, 1018 + pds_xrpc_client: None, 1019 + pds_xrpc_client_override: None, 1020 + run_id: "test-run-id", 899 1021 }; 900 1022 901 1023 let report = run_pipeline(target, opts).await; ··· 922 1044 let fake_tee = common::FakeRawHttpTee::new(); 923 1045 fake_tee.add_response(None, 200, br#"{"cursor": null, "labels": []}"#.to_vec()); 924 1046 let fake_ws = common::FakeWebSocketClient::empty(); 1047 + let fake_report_tee = common::FakeCreateReportTee::new(); 925 1048 926 1049 let opts = LabelerOptions { 927 1050 http: &http, ··· 930 1053 ws_client: Some(&fake_ws), 931 1054 subscribe_timeout: Duration::from_secs(5), 932 1055 verbose: false, 1056 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 1057 + commit_report: false, 1058 + force_self_mint: false, 1059 + self_mint_curve: SelfMintCurve::Es256k, 1060 + report_subject_override: None, 1061 + self_mint_signer: None, 1062 + pds_credentials: None, 1063 + pds_xrpc_client: None, 1064 + pds_xrpc_client_override: None, 1065 + run_id: "test-run-id", 933 1066 }; 934 1067 935 1068 let report = run_pipeline(target, opts).await;
+134 -1
tests/labeler_identity.rs
··· 3 3 mod common; 4 4 5 5 use async_trait::async_trait; 6 + use atproto_devtool::commands::test::labeler::create_report::self_mint::SelfMintCurve; 6 7 use atproto_devtool::commands::test::labeler::pipeline::{ 7 - HttpTee, LabelerOptions, parse_target, run_pipeline, 8 + CreateReportTeeKind, HttpTee, LabelerOptions, parse_target, run_pipeline, 8 9 }; 9 10 use atproto_devtool::common::identity::{DnsResolver, HttpClient, IdentityError}; 10 11 use std::collections::HashMap; ··· 146 147 let fake_tee = common::FakeRawHttpTee::new(); 147 148 fake_tee.add_response(None, 200, healthy_labels_response()); 148 149 let fake_ws = common::FakeWebSocketClient::empty(); 150 + let fake_report_tee = common::FakeCreateReportTee::new(); 149 151 150 152 let opts = LabelerOptions { 151 153 http: &http, ··· 154 156 ws_client: Some(&fake_ws), 155 157 subscribe_timeout: std::time::Duration::from_secs(5), 156 158 verbose: false, 159 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 160 + commit_report: false, 161 + force_self_mint: false, 162 + self_mint_curve: SelfMintCurve::Es256k, 163 + report_subject_override: None, 164 + self_mint_signer: None, 165 + pds_credentials: None, 166 + pds_xrpc_client: None, 167 + pds_xrpc_client_override: None, 168 + run_id: "test-run-id", 157 169 }; 158 170 159 171 let report = run_pipeline(target, opts).await; ··· 173 185 fake_tee.add_response(None, 200, empty_response); 174 186 175 187 let fake_ws = common::FakeWebSocketClient::empty(); 188 + let fake_report_tee = common::FakeCreateReportTee::new(); 176 189 177 190 let opts = LabelerOptions { 178 191 http: &http, ··· 181 194 ws_client: Some(&fake_ws), 182 195 subscribe_timeout: std::time::Duration::from_secs(5), 183 196 verbose: false, 197 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 198 + commit_report: false, 199 + force_self_mint: false, 200 + self_mint_curve: SelfMintCurve::Es256k, 201 + report_subject_override: None, 202 + self_mint_signer: None, 203 + pds_credentials: None, 204 + pds_xrpc_client: None, 205 + pds_xrpc_client_override: None, 206 + run_id: "test-run-id", 184 207 }; 185 208 186 209 let report = run_pipeline(target, opts).await; ··· 223 246 fake_tee.add_response(None, 200, empty_response); 224 247 225 248 let fake_ws = common::FakeWebSocketClient::empty(); 249 + let fake_report_tee = common::FakeCreateReportTee::new(); 226 250 227 251 let opts = LabelerOptions { 228 252 http: &http, ··· 231 255 ws_client: Some(&fake_ws), 232 256 subscribe_timeout: std::time::Duration::from_secs(5), 233 257 verbose: false, 258 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 259 + commit_report: false, 260 + force_self_mint: false, 261 + self_mint_curve: SelfMintCurve::Es256k, 262 + report_subject_override: None, 263 + self_mint_signer: None, 264 + pds_credentials: None, 265 + pds_xrpc_client: None, 266 + pds_xrpc_client_override: None, 267 + run_id: "test-run-id", 234 268 }; 235 269 236 270 let report = run_pipeline(target, opts).await; ··· 265 299 let fake_tee = common::FakeRawHttpTee::new(); 266 300 fake_tee.add_response(None, 200, healthy_labels_response()); 267 301 let fake_ws = common::FakeWebSocketClient::empty(); 302 + let fake_report_tee = common::FakeCreateReportTee::new(); 268 303 269 304 let opts = LabelerOptions { 270 305 http: &http, ··· 273 308 ws_client: Some(&fake_ws), 274 309 subscribe_timeout: std::time::Duration::from_secs(5), 275 310 verbose: false, 311 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 312 + commit_report: false, 313 + force_self_mint: false, 314 + self_mint_curve: SelfMintCurve::Es256k, 315 + report_subject_override: None, 316 + self_mint_signer: None, 317 + pds_credentials: None, 318 + pds_xrpc_client: None, 319 + pds_xrpc_client_override: None, 320 + run_id: "test-run-id", 276 321 }; 277 322 278 323 let report = run_pipeline(target, opts).await; ··· 309 354 fake_tee.add_response(None, 200, empty_response); 310 355 311 356 let fake_ws = common::FakeWebSocketClient::empty(); 357 + let fake_report_tee = common::FakeCreateReportTee::new(); 312 358 313 359 let opts = LabelerOptions { 314 360 http: &http, ··· 317 363 ws_client: Some(&fake_ws), 318 364 subscribe_timeout: std::time::Duration::from_secs(5), 319 365 verbose: false, 366 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 367 + commit_report: false, 368 + force_self_mint: false, 369 + self_mint_curve: SelfMintCurve::Es256k, 370 + report_subject_override: None, 371 + self_mint_signer: None, 372 + pds_credentials: None, 373 + pds_xrpc_client: None, 374 + pds_xrpc_client_override: None, 375 + run_id: "test-run-id", 320 376 }; 321 377 322 378 let report = run_pipeline(target, opts).await; ··· 338 394 fake_tee.add_response(None, 200, empty_response); 339 395 340 396 let fake_ws = common::FakeWebSocketClient::empty(); 397 + let fake_report_tee = common::FakeCreateReportTee::new(); 341 398 342 399 let opts = LabelerOptions { 343 400 http: &http, ··· 346 403 ws_client: Some(&fake_ws), 347 404 subscribe_timeout: std::time::Duration::from_secs(5), 348 405 verbose: false, 406 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 407 + commit_report: false, 408 + force_self_mint: false, 409 + self_mint_curve: SelfMintCurve::Es256k, 410 + report_subject_override: None, 411 + self_mint_signer: None, 412 + pds_credentials: None, 413 + pds_xrpc_client: None, 414 + pds_xrpc_client_override: None, 415 + run_id: "test-run-id", 349 416 }; 350 417 351 418 let report = run_pipeline(target, opts).await; ··· 378 445 let fake_tee = common::FakeRawHttpTee::new(); 379 446 fake_tee.add_response(None, 200, healthy_labels_response()); 380 447 let fake_ws = common::FakeWebSocketClient::empty(); 448 + let fake_report_tee = common::FakeCreateReportTee::new(); 381 449 382 450 let opts = LabelerOptions { 383 451 http: &http, ··· 386 454 ws_client: Some(&fake_ws), 387 455 subscribe_timeout: std::time::Duration::from_secs(5), 388 456 verbose: false, 457 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 458 + commit_report: false, 459 + force_self_mint: false, 460 + self_mint_curve: SelfMintCurve::Es256k, 461 + report_subject_override: None, 462 + self_mint_signer: None, 463 + pds_credentials: None, 464 + pds_xrpc_client: None, 465 + pds_xrpc_client_override: None, 466 + run_id: "test-run-id", 389 467 }; 390 468 391 469 let report = run_pipeline(target, opts).await; ··· 423 501 fake_tee.add_response(None, 200, empty_response); 424 502 425 503 let fake_ws = common::FakeWebSocketClient::empty(); 504 + let fake_report_tee = common::FakeCreateReportTee::new(); 426 505 427 506 let opts = LabelerOptions { 428 507 http: &http, ··· 431 510 ws_client: Some(&fake_ws), 432 511 subscribe_timeout: std::time::Duration::from_secs(5), 433 512 verbose: false, 513 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 514 + commit_report: false, 515 + force_self_mint: false, 516 + self_mint_curve: SelfMintCurve::Es256k, 517 + report_subject_override: None, 518 + self_mint_signer: None, 519 + pds_credentials: None, 520 + pds_xrpc_client: None, 521 + pds_xrpc_client_override: None, 522 + run_id: "test-run-id", 434 523 }; 435 524 436 525 let report = run_pipeline(target, opts).await; ··· 470 559 fake_tee.add_response(None, 200, empty_response); 471 560 472 561 let fake_ws = common::FakeWebSocketClient::empty(); 562 + let fake_report_tee = common::FakeCreateReportTee::new(); 473 563 474 564 let opts = LabelerOptions { 475 565 http: &http, ··· 478 568 ws_client: Some(&fake_ws), 479 569 subscribe_timeout: std::time::Duration::from_secs(5), 480 570 verbose: false, 571 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 572 + commit_report: false, 573 + force_self_mint: false, 574 + self_mint_curve: SelfMintCurve::Es256k, 575 + report_subject_override: None, 576 + self_mint_signer: None, 577 + pds_credentials: None, 578 + pds_xrpc_client: None, 579 + pds_xrpc_client_override: None, 580 + run_id: "test-run-id", 481 581 }; 482 582 483 583 let report = run_pipeline(target, opts).await; ··· 515 615 fake_tee.add_response(None, 200, empty_response); 516 616 517 617 let fake_ws = common::FakeWebSocketClient::empty(); 618 + let fake_report_tee = common::FakeCreateReportTee::new(); 518 619 519 620 let opts = LabelerOptions { 520 621 http: &http, ··· 523 624 ws_client: Some(&fake_ws), 524 625 subscribe_timeout: std::time::Duration::from_secs(5), 525 626 verbose: false, 627 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 628 + commit_report: false, 629 + force_self_mint: false, 630 + self_mint_curve: SelfMintCurve::Es256k, 631 + report_subject_override: None, 632 + self_mint_signer: None, 633 + pds_credentials: None, 634 + pds_xrpc_client: None, 635 + pds_xrpc_client_override: None, 636 + run_id: "test-run-id", 526 637 }; 527 638 528 639 let report = run_pipeline(target, opts).await; ··· 560 671 fake_tee.add_response(None, 200, empty_response); 561 672 562 673 let fake_ws = common::FakeWebSocketClient::empty(); 674 + let fake_report_tee = common::FakeCreateReportTee::new(); 563 675 564 676 let opts = LabelerOptions { 565 677 http: &http, ··· 568 680 ws_client: Some(&fake_ws), 569 681 subscribe_timeout: std::time::Duration::from_secs(5), 570 682 verbose: false, 683 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 684 + commit_report: false, 685 + force_self_mint: false, 686 + self_mint_curve: SelfMintCurve::Es256k, 687 + report_subject_override: None, 688 + self_mint_signer: None, 689 + pds_credentials: None, 690 + pds_xrpc_client: None, 691 + pds_xrpc_client_override: None, 692 + run_id: "test-run-id", 571 693 }; 572 694 573 695 let report = run_pipeline(target, opts).await; ··· 609 731 fake_tee.add_response(None, 200, empty_response); 610 732 611 733 let fake_ws = common::FakeWebSocketClient::empty(); 734 + let fake_report_tee = common::FakeCreateReportTee::new(); 612 735 613 736 let opts = LabelerOptions { 614 737 http: &http, ··· 617 740 ws_client: Some(&fake_ws), 618 741 subscribe_timeout: std::time::Duration::from_secs(5), 619 742 verbose: false, 743 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 744 + commit_report: false, 745 + force_self_mint: false, 746 + self_mint_curve: SelfMintCurve::Es256k, 747 + report_subject_override: None, 748 + self_mint_signer: None, 749 + pds_credentials: None, 750 + pds_xrpc_client: None, 751 + pds_xrpc_client_override: None, 752 + run_id: "test-run-id", 620 753 }; 621 754 622 755 let report = run_pipeline(target, opts).await;
+237 -8
tests/labeler_report.rs
··· 994 994 // Task 4 tests: AC5 and AC6 PDS-mode integration tests 995 995 996 996 #[tokio::test] 997 - #[ignore] 998 997 async fn ac5_1_full_flow_passes() { 999 998 let facts = local_identity_facts(); 999 + let signer = SelfMintSigner::spawn(SelfMintCurve::Es256k).await.unwrap(); 1000 1000 let tee = FakeCreateReportTee::new(); 1001 1001 let pds_client = common::FakePdsXrpcClient::new(); 1002 1002 1003 - // Queue responses for Phase 5 (2), Phase 6 (4), Phase 7 (1): all unauthorized. 1004 - for _ in 0..7 { 1005 - tee.enqueue(common::FakeCreateReportResponse::unauthorized("x", "y")); 1006 - } 1003 + // Queue responses for labeler tee: 1004 + // Phase 5 (2): unauth_rejected, malformed_bearer_rejected. 1005 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1006 + "AuthenticationRequired", 1007 + "jwt required", 1008 + )); 1009 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1010 + "BadJwt", 1011 + "invalid bearer", 1012 + )); 1013 + // Phase 6 (4): wrong_aud_rejected, wrong_lxm_rejected, expired_rejected, rejected_shape_returns_400. 1014 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1015 + "BadJwtAudience", 1016 + "aud mismatch", 1017 + )); 1018 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1019 + "BadJwtLexiconMethod", 1020 + "lxm mismatch", 1021 + )); 1022 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1023 + "JwtExpired", 1024 + "expired", 1025 + )); 1026 + tee.enqueue(common::FakeCreateReportResponse::bad_request( 1027 + "InvalidRequest", 1028 + "unadvertised reasonType", 1029 + )); 1030 + // Phase 7 (1): self_mint_accepted. 1031 + tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1032 + // Phase 8 (1): pds_service_auth_accepted (service-auth mode POST). 1033 + tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1007 1034 1008 1035 // Queue PDS responses: 1009 1036 // 1. createSession (for fetch_session_and_did). ··· 1043 1070 .into_bytes(), 1044 1071 }); 1045 1072 1046 - // Labeler POST via report_tee (AC5.1): returns 200 for service-auth mode. 1047 - tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1048 - 1049 1073 let pds_creds = atproto_devtool::commands::test::labeler::pipeline::PdsCredentials { 1050 1074 handle: "alice.bsky.social".to_string(), 1051 1075 app_password: "xxxx-xxxx-xxxx-xxxx".to_string(), 1052 1076 }; 1053 1077 let mut opts = default_opts(); 1078 + opts.self_mint_signer = Some(&signer); 1054 1079 opts.pds_credentials = Some(&pds_creds); 1055 1080 opts.pds_xrpc_client = Some(&pds_client); 1056 1081 opts.commit_report = true; ··· 1060 1085 let results = run_report_stage(&facts, &tee, opts).await; 1061 1086 1062 1087 assert_eq!(results.len(), 10, "AC7.1 requires exactly 10 rows"); 1088 + assert_eq!(results[7].id, "report::self_mint_accepted"); 1089 + assert_eq!(results[7].status, CheckStatus::Pass); 1063 1090 assert_eq!(results[8].id, "report::pds_service_auth_accepted"); 1064 1091 assert_eq!(results[8].status, CheckStatus::Pass); 1065 1092 assert_eq!(results[9].id, "report::pds_proxied_accepted"); ··· 1522 1549 ); 1523 1550 } 1524 1551 } 1552 + 1553 + #[tokio::test] 1554 + async fn report_all_pass_local_labeler_snapshot() { 1555 + // E2E test: local labeler, self-mint signer, commit=true, NO PDS credentials. 1556 + // Expected: 8 Pass + 2 Skipped (PDS not provided). 1557 + let facts = local_identity_facts(); 1558 + let signer = SelfMintSigner::spawn(SelfMintCurve::Es256k).await.unwrap(); 1559 + let tee = FakeCreateReportTee::new(); 1560 + 1561 + // Queue responses for Phase 5 (2), Phase 6 (4), Phase 7 (1). 1562 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1563 + "AuthenticationRequired", 1564 + "jwt required", 1565 + )); 1566 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1567 + "BadJwt", 1568 + "invalid bearer", 1569 + )); 1570 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1571 + "BadJwtAudience", 1572 + "aud mismatch", 1573 + )); 1574 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1575 + "BadJwtLexiconMethod", 1576 + "lxm mismatch", 1577 + )); 1578 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1579 + "JwtExpired", 1580 + "expired", 1581 + )); 1582 + tee.enqueue(common::FakeCreateReportResponse::bad_request( 1583 + "InvalidRequest", 1584 + "unadvertised reasonType", 1585 + )); 1586 + tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1587 + 1588 + let mut opts = default_opts(); 1589 + opts.self_mint_signer = Some(&signer); 1590 + opts.commit_report = true; 1591 + opts.pds_credentials = None; 1592 + let run_id = "test-run-1234567890".to_string(); 1593 + opts.run_id = &run_id; 1594 + 1595 + let results = run_report_stage(&facts, &tee, opts).await; 1596 + let rendered = render_results_to_string(results).await; 1597 + insta::assert_snapshot!("report_all_pass_local_labeler_snapshot", rendered); 1598 + } 1599 + 1600 + #[tokio::test] 1601 + async fn report_all_pass_full_suite_snapshot() { 1602 + // E2E test: local labeler, self-mint signer, commit=true, WITH PDS credentials. 1603 + // Expected: all 10 Pass. 1604 + let facts = local_identity_facts(); 1605 + let signer = SelfMintSigner::spawn(SelfMintCurve::Es256k).await.unwrap(); 1606 + let tee = FakeCreateReportTee::new(); 1607 + let pds_client = common::FakePdsXrpcClient::new(); 1608 + 1609 + // Queue labeler responses: Phase 5 (2), Phase 6 (4), Phase 7 (1), Phase 8 (1). 1610 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1611 + "AuthenticationRequired", 1612 + "jwt required", 1613 + )); 1614 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1615 + "BadJwt", 1616 + "invalid bearer", 1617 + )); 1618 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1619 + "BadJwtAudience", 1620 + "aud mismatch", 1621 + )); 1622 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1623 + "BadJwtLexiconMethod", 1624 + "lxm mismatch", 1625 + )); 1626 + tee.enqueue(common::FakeCreateReportResponse::unauthorized( 1627 + "JwtExpired", 1628 + "expired", 1629 + )); 1630 + tee.enqueue(common::FakeCreateReportResponse::bad_request( 1631 + "InvalidRequest", 1632 + "unadvertised reasonType", 1633 + )); 1634 + tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1635 + tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1636 + 1637 + // Queue PDS responses. 1638 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1639 + status: 200, 1640 + body: serde_json::json!({ 1641 + "accessJwt": "test-jwt-token", 1642 + "did": "did:plc:test-user-did" 1643 + }) 1644 + .to_string() 1645 + .into_bytes(), 1646 + }); 1647 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1648 + status: 200, 1649 + body: serde_json::json!({ 1650 + "accessJwt": "test-jwt-token", 1651 + "did": "did:plc:test-user-did" 1652 + }) 1653 + .to_string() 1654 + .into_bytes(), 1655 + }); 1656 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1657 + status: 200, 1658 + body: serde_json::json!({ 1659 + "token": "service-auth-jwt" 1660 + }) 1661 + .to_string() 1662 + .into_bytes(), 1663 + }); 1664 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1665 + status: 200, 1666 + body: serde_json::json!({ "id": "report-id-123" }) 1667 + .to_string() 1668 + .into_bytes(), 1669 + }); 1670 + 1671 + let pds_creds = atproto_devtool::commands::test::labeler::pipeline::PdsCredentials { 1672 + handle: "alice.bsky.social".to_string(), 1673 + app_password: "xxxx-xxxx-xxxx-xxxx".to_string(), 1674 + }; 1675 + let mut opts = default_opts(); 1676 + opts.self_mint_signer = Some(&signer); 1677 + opts.pds_credentials = Some(&pds_creds); 1678 + opts.pds_xrpc_client = Some(&pds_client); 1679 + opts.commit_report = true; 1680 + let run_id = "test-run-1234567890".to_string(); 1681 + opts.run_id = &run_id; 1682 + 1683 + let results = run_report_stage(&facts, &tee, opts).await; 1684 + let rendered = render_results_to_string(results).await; 1685 + insta::assert_snapshot!("report_all_pass_full_suite_snapshot", rendered); 1686 + } 1687 + 1688 + #[tokio::test] 1689 + async fn report_all_fail_misconfigured_labeler_snapshot() { 1690 + // E2E test: labeler accepts everything (200 for every POST). 1691 + // Expected: contract_published Pass, all JWT checks SpecViolation, 1692 + // rejected_shape Advisory (200 when 400 expected), self_mint Pass, 1693 + // pds_service_auth Pass, pds_proxied Pass. 1694 + let facts = local_identity_facts(); 1695 + let signer = SelfMintSigner::spawn(SelfMintCurve::Es256k).await.unwrap(); 1696 + let tee = FakeCreateReportTee::new(); 1697 + let pds_client = common::FakePdsXrpcClient::new(); 1698 + 1699 + // Queue labeler responses: all 8 ok_empty (misconfigured to accept everything). 1700 + for _ in 0..8 { 1701 + tee.enqueue(common::FakeCreateReportResponse::ok_empty()); 1702 + } 1703 + 1704 + // Queue PDS responses. 1705 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1706 + status: 200, 1707 + body: serde_json::json!({ 1708 + "accessJwt": "test-jwt-token", 1709 + "did": "did:plc:test-user-did" 1710 + }) 1711 + .to_string() 1712 + .into_bytes(), 1713 + }); 1714 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1715 + status: 200, 1716 + body: serde_json::json!({ 1717 + "accessJwt": "test-jwt-token", 1718 + "did": "did:plc:test-user-did" 1719 + }) 1720 + .to_string() 1721 + .into_bytes(), 1722 + }); 1723 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1724 + status: 200, 1725 + body: serde_json::json!({ 1726 + "token": "service-auth-jwt" 1727 + }) 1728 + .to_string() 1729 + .into_bytes(), 1730 + }); 1731 + pds_client.enqueue(common::FakePdsXrpcResponse::Response { 1732 + status: 200, 1733 + body: serde_json::json!({ "id": "report-id-123" }) 1734 + .to_string() 1735 + .into_bytes(), 1736 + }); 1737 + 1738 + let pds_creds = atproto_devtool::commands::test::labeler::pipeline::PdsCredentials { 1739 + handle: "alice.bsky.social".to_string(), 1740 + app_password: "xxxx-xxxx-xxxx-xxxx".to_string(), 1741 + }; 1742 + let mut opts = default_opts(); 1743 + opts.self_mint_signer = Some(&signer); 1744 + opts.pds_credentials = Some(&pds_creds); 1745 + opts.pds_xrpc_client = Some(&pds_client); 1746 + opts.commit_report = true; 1747 + let run_id = "test-run-1234567890".to_string(); 1748 + opts.run_id = &run_id; 1749 + 1750 + let results = run_report_stage(&facts, &tee, opts).await; 1751 + let rendered = render_results_to_string(results).await; 1752 + insta::assert_snapshot!("report_all_fail_misconfigured_labeler_snapshot", rendered); 1753 + }
+90 -1
tests/labeler_subscription.rs
··· 7 7 8 8 mod common; 9 9 10 + use atproto_devtool::commands::test::labeler::create_report::self_mint::SelfMintCurve; 10 11 use atproto_devtool::commands::test::labeler::pipeline::{ 11 - HttpTee, LabelerOptions, parse_target, run_pipeline, 12 + CreateReportTeeKind, HttpTee, LabelerOptions, parse_target, run_pipeline, 12 13 }; 13 14 use atproto_devtool::commands::test::labeler::subscription::{FrameHeader, SubscribeLabelsPayload}; 14 15 use atproto_devtool::common::identity::{DnsResolver, HttpClient, IdentityError}; ··· 269 270 "tests/fixtures/labeler/subscription/backfill_complete/frames.bin", 270 271 ); 271 272 let fake_ws = common::FakeWebSocketClient::new(); 273 + let fake_report_tee = common::FakeCreateReportTee::new(); 272 274 273 275 // Add first connection (backfill): 3 frames with 10ms delay, then 600ms idle gap. 274 276 fake_ws.add_script(common::FakeScript { ··· 291 293 ws_client: Some(&fake_ws), 292 294 subscribe_timeout: Duration::from_secs(2), 293 295 verbose: false, 296 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 297 + commit_report: false, 298 + force_self_mint: false, 299 + self_mint_curve: SelfMintCurve::Es256k, 300 + report_subject_override: None, 301 + self_mint_signer: None, 302 + pds_credentials: None, 303 + pds_xrpc_client: None, 304 + pds_xrpc_client_override: None, 305 + run_id: "test-run-id", 294 306 }; 295 307 296 308 let report = run_pipeline(target, opts).await; ··· 305 317 "tests/fixtures/labeler/subscription/backfill_exceeds_budget/frames.bin", 306 318 ); 307 319 let fake_ws = common::FakeWebSocketClient::new(); 320 + let fake_report_tee = common::FakeCreateReportTee::new(); 308 321 309 322 // First connection (backfill): 20 frames @ 150ms delay = 3s total (exceeds 2s budget). 310 323 fake_ws.add_script(common::FakeScript { ··· 339 352 ws_client: Some(&fake_ws), 340 353 subscribe_timeout: Duration::from_secs(2), 341 354 verbose: false, 355 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 356 + commit_report: false, 357 + force_self_mint: false, 358 + self_mint_curve: SelfMintCurve::Es256k, 359 + report_subject_override: None, 360 + self_mint_signer: None, 361 + pds_credentials: None, 362 + pds_xrpc_client: None, 363 + pds_xrpc_client_override: None, 364 + run_id: "test-run-id", 342 365 }; 343 366 344 367 let report = run_pipeline(target, opts).await; ··· 350 373 #[tokio::test(flavor = "current_thread", start_paused = true)] 351 374 async fn empty_stream_advisories() { 352 375 let fake_ws = common::FakeWebSocketClient::new(); 376 + let fake_report_tee = common::FakeCreateReportTee::new(); 353 377 354 378 // Single connection (backfill): empty stream returns no frames immediately, 355 379 // so backfill outcome is NoFramesWithinBudget and live-tail is skipped. ··· 373 397 ws_client: Some(&fake_ws), 374 398 subscribe_timeout: Duration::from_secs(2), 375 399 verbose: false, 400 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 401 + commit_report: false, 402 + force_self_mint: false, 403 + self_mint_curve: SelfMintCurve::Es256k, 404 + report_subject_override: None, 405 + self_mint_signer: None, 406 + pds_credentials: None, 407 + pds_xrpc_client: None, 408 + pds_xrpc_client_override: None, 409 + run_id: "test-run-id", 376 410 }; 377 411 378 412 let report = run_pipeline(target, opts).await; ··· 386 420 let frames = 387 421 load_frames_from_fixture("tests/fixtures/labeler/subscription/malformed_frame/frames.bin"); 388 422 let fake_ws = common::FakeWebSocketClient::new(); 423 + let fake_report_tee = common::FakeCreateReportTee::new(); 389 424 390 425 // First connection (backfill): frames then stream close. 391 426 fake_ws.add_script(common::FakeScript { ··· 418 453 ws_client: Some(&fake_ws), 419 454 subscribe_timeout: Duration::from_secs(2), 420 455 verbose: false, 456 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 457 + commit_report: false, 458 + force_self_mint: false, 459 + self_mint_curve: SelfMintCurve::Es256k, 460 + report_subject_override: None, 461 + self_mint_signer: None, 462 + pds_credentials: None, 463 + pds_xrpc_client: None, 464 + pds_xrpc_client_override: None, 465 + run_id: "test-run-id", 421 466 }; 422 467 423 468 let report = run_pipeline(target, opts).await; ··· 432 477 "tests/fixtures/labeler/subscription/error_frame_malformed/frames.bin", 433 478 ); 434 479 let fake_ws = common::FakeWebSocketClient::new(); 480 + let fake_report_tee = common::FakeCreateReportTee::new(); 435 481 436 482 // First connection (backfill): frames then stream close. 437 483 fake_ws.add_script(common::FakeScript { ··· 464 510 ws_client: Some(&fake_ws), 465 511 subscribe_timeout: Duration::from_secs(2), 466 512 verbose: false, 513 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 514 + commit_report: false, 515 + force_self_mint: false, 516 + self_mint_curve: SelfMintCurve::Es256k, 517 + report_subject_override: None, 518 + self_mint_signer: None, 519 + pds_credentials: None, 520 + pds_xrpc_client: None, 521 + pds_xrpc_client_override: None, 522 + run_id: "test-run-id", 467 523 }; 468 524 469 525 let report = run_pipeline(target, opts).await; ··· 475 531 #[tokio::test(flavor = "current_thread", start_paused = true)] 476 532 async fn unreachable_endpoint_network_error() { 477 533 let fake_ws = common::FakeWebSocketClient::new(); 534 + let fake_report_tee = common::FakeCreateReportTee::new(); 478 535 479 536 // First connection returns transport error. 480 537 fake_ws.add_script(common::FakeScript { ··· 497 554 ws_client: Some(&fake_ws), 498 555 subscribe_timeout: Duration::from_secs(2), 499 556 verbose: false, 557 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 558 + commit_report: false, 559 + force_self_mint: false, 560 + self_mint_curve: SelfMintCurve::Es256k, 561 + report_subject_override: None, 562 + self_mint_signer: None, 563 + pds_credentials: None, 564 + pds_xrpc_client: None, 565 + pds_xrpc_client_override: None, 566 + run_id: "test-run-id", 500 567 }; 501 568 502 569 let report = run_pipeline(target, opts).await; ··· 511 578 "tests/fixtures/labeler/subscription/backfill_exceeds_budget/frames.bin", 512 579 ); 513 580 let fake_ws = common::FakeWebSocketClient::new(); 581 + let fake_report_tee = common::FakeCreateReportTee::new(); 514 582 515 583 // First connection (backfill): 20 frames @ 150ms delay = 3s total (exceeds 2s budget). 516 584 fake_ws.add_script(common::FakeScript { ··· 542 610 ws_client: Some(&fake_ws), 543 611 subscribe_timeout: Duration::from_secs(2), 544 612 verbose: false, 613 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 614 + commit_report: false, 615 + force_self_mint: false, 616 + self_mint_curve: SelfMintCurve::Es256k, 617 + report_subject_override: None, 618 + self_mint_signer: None, 619 + pds_credentials: None, 620 + pds_xrpc_client: None, 621 + pds_xrpc_client_override: None, 622 + run_id: "test-run-id", 545 623 }; 546 624 547 625 let report = run_pipeline(target, opts).await; ··· 574 652 } 575 653 576 654 let fake_ws = common::FakeWebSocketClient::new(); 655 + let fake_report_tee = common::FakeCreateReportTee::new(); 577 656 578 657 // Single connection (backfill): 2 frames (10ms apart), then transport error, then final_wait 579 658 // to exhaust idle-gap timer from last frame. The idle-gap should fire from the second frame, ··· 598 677 ws_client: Some(&fake_ws), 599 678 subscribe_timeout: Duration::from_secs(2), 600 679 verbose: false, 680 + create_report_tee: CreateReportTeeKind::Test(&fake_report_tee), 681 + commit_report: false, 682 + force_self_mint: false, 683 + self_mint_curve: SelfMintCurve::Es256k, 684 + report_subject_override: None, 685 + self_mint_signer: None, 686 + pds_credentials: None, 687 + pds_xrpc_client: None, 688 + pds_xrpc_client_override: None, 689 + run_id: "test-run-id", 601 690 }; 602 691 603 692 let report = run_pipeline(target, opts).await;
+47
tests/snapshots/labeler_report__report_all_fail_misconfigured_labeler_snapshot.snap
··· 1 + --- 2 + source: tests/labeler_report.rs 3 + expression: rendered 4 + --- 5 + Target: test-labeler 6 + Resolved DID: did:plc:aaa22222222222222222bbbbbb 7 + PDS endpoint: https://pds.example.com/ 8 + Labeler endpoint: https://labeler.example.com/ 9 + elapsed: XXms 10 + 11 + == Report == 12 + [OK] Labeler advertises reportable shape 13 + [FAIL] Unauthenticated report accepted (should have been rejected) 14 + labeler::report::unauthenticated_accepted 15 + 16 + × Labeler accepted unauthenticated createReport (status 200) 17 + help: A labeler must reject createReport with 401 when no Authorization header is supplied. 18 + [FAIL] Malformed bearer accepted (should have been rejected) 19 + labeler::report::malformed_bearer_accepted 20 + 21 + × Labeler accepted malformed Bearer token (status 200) 22 + help: A labeler must reject createReport with 401 when the Authorization header carries a non-JWT string. 23 + [FAIL] JWT with wrong `aud` accepted 24 + labeler::report::wrong_aud_accepted 25 + 26 + × Labeler accepted JWT with wrong `aud` (status 200) 27 + help: A labeler must reject JWTs whose `aud` claim does not match its own DID. 28 + [FAIL] JWT with wrong `lxm` accepted 29 + labeler::report::wrong_lxm_accepted 30 + 31 + × Labeler accepted JWT with wrong `lxm` (status 200) 32 + help: A labeler must reject JWTs whose `lxm` claim does not match the invoked Lexicon method. 33 + [FAIL] Expired JWT accepted 34 + labeler::report::expired_accepted 35 + 36 + × Labeler accepted expired JWT (status 200) 37 + help: A labeler must reject JWTs whose `exp` claim is in the past. 38 + [WARN] Rejection status was not 400 InvalidRequest 39 + labeler::report::shape_not_400 40 + 41 + × Unadvertised `reasonType` was rejected with status 200, expected 400 InvalidRequest 42 + help: A labeler should return 400 InvalidRequest (not 401 or 500) for a `reasonType` not listed in its published LabelerPolicies.reasonTypes. 43 + [OK] Self-mint report accepted 44 + [OK] PDS-minted JWT accepted 45 + [OK] PDS-proxied report accepted 46 + 47 + Summary: 4 passed, 5 failed (spec), 0 network errors, 1 advisories, 0 skipped. Exit code: 1
+23
tests/snapshots/labeler_report__report_all_pass_full_suite_snapshot.snap
··· 1 + --- 2 + source: tests/labeler_report.rs 3 + expression: rendered 4 + --- 5 + Target: test-labeler 6 + Resolved DID: did:plc:aaa22222222222222222bbbbbb 7 + PDS endpoint: https://pds.example.com/ 8 + Labeler endpoint: https://labeler.example.com/ 9 + elapsed: XXms 10 + 11 + == Report == 12 + [OK] Labeler advertises reportable shape 13 + [OK] Unauthenticated report rejected 14 + [OK] Malformed bearer rejected 15 + [OK] JWT with wrong `aud` rejected 16 + [OK] JWT with wrong `lxm` rejected 17 + [OK] Expired JWT rejected 18 + [OK] Invalid shape returns 400 InvalidRequest 19 + [OK] Self-mint report accepted 20 + [OK] PDS-minted JWT accepted 21 + [OK] PDS-proxied report accepted 22 + 23 + Summary: 10 passed, 0 failed (spec), 0 network errors, 0 advisories, 0 skipped. Exit code: 0
+23
tests/snapshots/labeler_report__report_all_pass_local_labeler_snapshot.snap
··· 1 + --- 2 + source: tests/labeler_report.rs 3 + expression: rendered 4 + --- 5 + Target: test-labeler 6 + Resolved DID: did:plc:aaa22222222222222222bbbbbb 7 + PDS endpoint: https://pds.example.com/ 8 + Labeler endpoint: https://labeler.example.com/ 9 + elapsed: XXms 10 + 11 + == Report == 12 + [OK] Labeler advertises reportable shape 13 + [OK] Unauthenticated report rejected 14 + [OK] Malformed bearer rejected 15 + [OK] JWT with wrong `aud` rejected 16 + [OK] JWT with wrong `lxm` rejected 17 + [OK] Expired JWT rejected 18 + [OK] Invalid shape returns 400 InvalidRequest 19 + [OK] Self-mint report accepted 20 + [SKIP] PDS-minted JWT accepted — requires --handle, --app-password, and --commit-report 21 + [SKIP] PDS-proxied report accepted — requires --handle, --app-password, and --commit-report 22 + 23 + Summary: 8 passed, 0 failed (spec), 0 network errors, 0 advisories, 2 skipped. Exit code: 0
+1 -1
tests/snapshots/labeler_subscription__backfill_exceeds_budget_triggers_live_tail.snap
··· 22 22 [WARN] Labeler has no published labels 23 23 [OK] First page was complete; pagination not exercised 24 24 == Subscription == 25 - [WARN] Subscription backfill stream closed unexpectedly 25 + [WARN] Subscription backfill exceeded budget 26 26 [OK] Subscription live-tail connection held 27 27 == Crypto == 28 28 [SKIP] Crypto stage (not run) — identity stage produced no labeler endpoint
+1 -2
tests/snapshots/labeler_subscription__empty_stream_advisories.snap
··· 1 1 --- 2 2 source: tests/labeler_subscription.rs 3 - assertion_line: 390 4 3 expression: rendered 5 4 --- 6 5 Target: https://example.com/labeler 7 - elapsed: XXms 6 + elapsed: 0ms 8 7 9 8 == Identity == 10 9 [SKIP] target resolution — no DID supplied; run with a handle, a DID, or --did <did>
+1 -1
tests/snapshots/labeler_subscription__live_tail_connect_failure_emits_network_error.snap
··· 23 23 [OK] First page was complete; pagination not exercised 24 24 == Subscription == 25 25 [NET] Subscription live-tail reachability 26 - [WARN] Subscription backfill stream closed unexpectedly 26 + [WARN] Subscription backfill exceeded budget 27 27 == Crypto == 28 28 [SKIP] Crypto stage (not run) — identity stage produced no labeler endpoint 29 29 == Report ==
+1 -2
tests/snapshots/labeler_subscription__unreachable_endpoint_network_error.snap
··· 1 1 --- 2 2 source: tests/labeler_subscription.rs 3 - assertion_line: 544 4 3 expression: rendered 5 4 --- 6 5 Target: https://example.com/labeler 7 - elapsed: XXms 6 + elapsed: 0ms 8 7 9 8 == Identity == 10 9 [SKIP] target resolution — no DID supplied; run with a handle, a DID, or --did <did>