Summary#
Adds a new report stage to atproto-devtool test labeler that exercises the full com.atproto.moderation.createReport authenticated-write path. The stage emits exactly 10 checks in a stable canonical order covering contract-published advertisement, no-JWT negatives (unauth + malformed bearer), self-mint negatives (wrong aud / lxm / exp / shape), the self-mint positive commit path, and two PDS-mediated positive modes (service-auth JWT and proxied createReport).
- 38 acceptance criteria (AC1.1–AC8.4) all covered by automated tests; 196 tests pass in debug mode.
- 11 stable
labeler::report::*miette diagnostic codes, each pinned by assertion + snapshot. - Pollution-avoidance helpers pick
reasonOther+ record subject for remote labelers, lex-first + own-DID for local ones, and always carry a sentinel reason"atproto-devtool conformance test <RFC3339> <run-id>". - Commit-gated:
--commit-reportrequired for any write-side check. - Locality gate:
--force-self-mintoverrides theis_local_labeler_hostnameheuristic. - New CLI flags:
--commit-report,--self-mint-curve <es256|es256k>,--force-self-mint,--report-subject-did,--handle,--app-password(symmetricrequires). - New primitives:
AnySigningKey, hand-rolled RFC 7515 compact JWS insrc/common/jwt.rs(ES256/ES256K only — no JWT library dep),encode_multikeycompanion toparse_multikey,is_local_labeler_hostname,SelfMintSignerwith an ephemeraldid:web:127.0.0.1%3A{port}identity server. - New seams:
CreateReportTee(production + fake),PdsXrpcClient(production + fake). No production network hop bypasses the seams. getrandom = "0.2"added as a direct dep (the transitiverand_coreinsideelliptic-curveis built without thegetrandomfeature).- CLAUDE.md files updated at repo root,
src/commands/test/labeler/, andsrc/common/.
Implementation plan and rationale: docs/implementation-plans/2026-04-17-labeler-report-stage/. Human test plan: docs/test-plans/2026-04-17-labeler-report-stage.md.
Test Plan#
-
cargo test— 196 passed / 1 ignored -
cargo clippy --all-targets -- -D warnings— clean -
cargo fmt --check— clean -
cargo build --release— clean - Phase 2 (read-only) against a real labeler: 10
report::*rows emitted in canonical order; write-side rows[SKIP] - Phase 3 (self-mint against a localhost labeler) with
--commit-report:self_mint_acceptedproduces exactly one moderation queue entry carrying the sentinel reason - Phase 5 (PDS modes) with
--handle+--app-password+--commit-report: 2 additional queue entries, authored by the real DID - Phase 6 (exit codes): 0 for conformant, 1 for SpecViolation, 2 for NetworkError
- Pre-release: replace
CONFORMANCE_REPORT_SUBJECT_URI/_CIDplaceholders insrc/commands/test/labeler/create_report/pollution.rswith real values
See the human test plan file for step-by-step verification.
🤖 Generated with Claude Code
Summary
- Branch labeler-report-stage pushed to origin with 58 commits.
- PR must be opened manually at the URL above (Tangled has no CLI integration in this environment).
- Worktree preserved at /home/str4d/dev/ai/atproto-devtool/.worktrees/labeler-report-stage.
- Reminder: human test plan at docs/test-plans/2026-04-17-labeler-report-stage.md documents end-to-end scenarios against a real labeler, the --commit-report sentinel grep-ability check, and the release-gate CONFORMANCE_REPORT_SUBJECT_URI placeholder replacement — review before considering this work fully complete.