Skip to content

fix(delivery): quarantine review bodies per comment - #2203

Merged
ScriptedAlchemy merged 1 commit into
masterfrom
fleet/review-ingest-quarantine
Sep 26, 2026
Merged

ScriptedAlchemy merged 1 commit into
masterfrom
fleet/review-ingest-quarantine

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Fixes #2158

Root cause

Two defects combined, so that rust-lang/log#741 never published a review generation.

  1. The classifier. The issue guessed YAML, but the Nit: ... body was actually caught by the HTTP-header lane. parse_http_header_document accepted the first line Nit: the job short name is check, … as a header field (Nit is a legal field name). The second line View changes since the review has no colon, so the lane returned Malformed. sanitize_provider_metadata_text then quarantined the body. The same thing happened to Note: … prose followed by a blank line and a paragraph.
  2. The decoder. graphql_comment_draft / rest_comment_draft used retained_review_body(body)?, so one unretainable body turned the whole read into None. That became GitHubReviewReadPortOutcomeV1::Unavailable, then GitHubReviewRefreshOutcomeV1::Unavailable, and nothing was stored, so the Delivery pull-request lane read not_published.

What changed

  • Privacy classifier. Without an HTTP start line, one leading Name: value line is weak evidence. If such a document stops being a header block (a line with no field, or content after the blank line), it is now prose for the raw credential scan. It stays a fail-closed Malformed quarantine only when a field it already exposed has a sensitive name. Requests with a start line keep the old behavior.
  • Per-body quarantine. GitHubReviewIngressResultV1 has a new field quarantined: Vec<GitHubReviewQuarantinedItemV1 { comment_id, reason }>. The reason is privacy_sanitizer or body_out_of_bounds. The list is ordered and disjoint from items.
    • The decoder validates every structural field first. Only when the body cannot be retained does it withhold that comment.
    • The full scan merges quarantined comments across pages.
    • Refresh normalization carries them forward and never synthesizes a Deleted lifecycle for a comment that is now quarantined.
  • Delivery and dashboard. Delivery projects the list on each operation snapshot (ProjectDeliveryGitHubOperationSnapshotV1.quarantined). The dashboard wire has DeliveryGitHubOperationSnapshotV1.quarantined (contracts regenerated). The Journey pull-request lane shows 1 quarantined (privacy sanitizer) on the read that withheld the comment.
  • Fixture. advisory/fixtures/rust_lang_log_741_review_threads.graphql.json is the production review-threads query as GitHub served it for Split MSRV used to build from MSRV used to test rust-lang/log#741. It has three bodies, one of them the Nit: literal.

Fail before / pass after

delivery::tests::one_quarantined_review_body_leaves_the_rest_of_the_pull_request_published replays the #741 capture through the production decoder, runtime transport, refresh coordinator, project store and Delivery read. The reply body is replaced by one the sanitizer must refuse (vault_passphrase: …\n broken: [unclosed). Result: two bodies ingested (4069686687, 4069691901 = the Nit: body), and quarantined == [{4069777906, PrivacySanitizer}] on a Ready lane.

Before (decoder and classifier fixes reverted):

panicked at crates/tracedecay-application/src/delivery.rs:3558:13:
the pull-request lane must publish: NotPublished after refresh Unavailable
test result: FAILED. 0 passed; 1 failed

After: ok.

structured_text_tests::code_shape::review_prose_opening_with_a_label_is_retained_as_prose (literal fixture). On master:

assertion `left == right` failed
  left: None
 right: Some("Nit: the job short name is check, the display name is build and we're actually running of the test, probably want to make that consistent.\nView changes since the review")

After: ok. The same test also asserts that Note: …\n\nSee … prose is retained and that X-Vault_Passphrase: ordinary-value\nsee … is still quarantined.

journey.test.ts › "counts a quarantined review comment on its provider read with the reason" asserts the lane detail complete · complete · 1 quarantined (privacy sanitizer) · head ….

Checks

  • cargo test -p tracedecay-privacy -p tracedecay-domain -p tracedecay-application -p tracedecay-dashboard-api --lib after rebase: 127 + 222 + 472 + 172 passed.
  • application_suite: 64 passed. domain_suite: 170 passed. pr_tracking: 7 passed.
  • cargo test -p tracedecay --features test-transport --test dashboard_api_test -- delivery: 4 passed.
  • contracts_suite: 275 passed, 1 failed. The failure, doctor_report_coverage_statement_is_truthful_about_unavailable_families, is pre-existing on master: feat(daemon): free retained state through one memory authority #2194 added an eighth doctor family and the test still expects 1/7.
  • cargo clippy -p tracedecay-privacy -p tracedecay-domain -p tracedecay-contracts -p tracedecay-application -p tracedecay-dashboard-api --all-targets -- -D warnings: clean.
  • cargo fmt --all -- --check: clean.
  • Dashboard: typecheck clean, pnpm test 2029 passed, contracts:check up to date.

The built-binary journey for rust-lang/log#741 (discovery found plus a populated Journey lane) needs the GitHub source binding provisioning from #2159, so it runs in that PR.

@changeset-bot

changeset-bot Bot commented Sep 26, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: dab8c4d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-26T11:05:30.210047Z dab8c4d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ScriptedAlchemy
ScriptedAlchemy merged commit 8e733c0 into master Sep 26, 2026
@ScriptedAlchemy
ScriptedAlchemy deleted the fleet/review-ingest-quarantine branch September 26, 2026 10:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dab8c4d960

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

{
Err(StructuredTextParseFailureV1::Malformed)
} else {
Ok(None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Scan later fields before falling back to prose

When a label-like first line is followed by colonless prose or a blank line, this closure checks only fields parsed before that boundary and immediately downgrades the entire body to the raw scanner. For example, Note: intro\nsome prose\nX-Vault_Passphrase:ordinary-value returns Ok(None) before inspecting the sensitive third-line key; the no-space header syntax also avoids the YAML mapping probe, and a low-entropy credential may not match any raw regex, so sanitize_provider_metadata_text can persist a value that the structured key detector would redact or quarantine. Inspect the remaining lines for sensitive field names before allowing this fallback.

AGENTS.md reference: AGENTS.md:L189-L190

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(delivery): one quarantined review body drops a PR's whole review ingest

1 participant