Skip to content

fix(cdc): keep raw exception diagnostics out of dead-letter headers - #192

Draft
seonghobae wants to merge 2 commits into
developfrom
fix/cdc-dlt-safe-exception-headers-622e5e6
Draft

fix(cdc): keep raw exception diagnostics out of dead-letter headers#192
seonghobae wants to merge 2 commits into
developfrom
fix/cdc-dlt-safe-exception-headers-622e5e6

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Advance #181 with one bounded data-governance/security slice from protected develop@622e5e6c3d534f230c390f10e3832efadfc01825. Protected replica-consumer dead-letter recovery inherited Spring Kafka defaults that published raw exception-message and exception-stacktrace headers with the failed record. JDBC/provider/credential-adjacent diagnostics do not belong in the replay envelope.

This direct-develop Draft changes only the real Kafka error-handler/test boundary. It does not choose a broker retention period, ACL system, encryption provider, tenant namespace, automatic replay policy, alternate payload store, or exactly-once claim. The failed record key/value and bounded origin/classification metadata remain recovery evidence in this first slice; full DLT retention/access/redrive governance stays in #181.

Exact current identity

  • protected/live base: develop@622e5e6c3d534f230c390f10e3832efadfc01825;
  • branch: fix/cdc-dlt-safe-exception-headers-622e5e6;
  • fail-first source head: 901a98e3bef05f63002602da8f228963ff698e63;
  • exact current GREEN source head: 58e21a9bda5aa1fe3fa2654f1f70f6c45bd3bbfd;
  • current synthetic merge preview: 910958c403635583ce2c353f04d033741cb6114e;
  • GitHub mergeability: true;
  • Draft: true;
  • formal reviews: none at the latest exact-head refresh;
  • unresolved review threads: zero at the latest exact-head refresh.

Every check/review from a predecessor source head is historical and does not transfer.

RCA

  • Immediate cause: DeadLetterPublishingRecoverer was created without narrowing its default exception headers.
  • Technical root cause: replay-capable dead-letter data and raw Java/provider diagnostic transport were coupled by framework defaults.
  • Control failure: existing KafkaConfigTest verified recoverer/backoff existence but never examined the actual produced DLT record/header boundary.
  • Product boundary: removing raw diagnostic headers is independently safe; final payload retention, ACL, encryption, redrive and deletion authority still require [Data governance/Reliability] Govern CDC dead-letter payload retention and replay authority #181's broader deployment/data-governance decision.

TDD evidence

RED — 901a98e3bef05f63002602da8f228963ff698e63

The fail-first commit changed only KafkaConfigTest. It obtains the actual production-configured DeadLetterPublishingRecoverer, recovers a realistic failed Kafka record whose exception contains a credential-bearing PostgreSQL URL, captures the real ProducerRecord, and requires:

  • the .DLT destination;
  • original key/value preserved for the currently selected recovery model;
  • original-topic and exception-class classification headers retained;
  • raw exception-message and exception-stacktrace DLT headers absent.

CI 31347680708, macOS job 93332556332, checked out synthetic merge a3818e868509d60bd7522d5ddf9a35480fd7731b (Merge 901a98e... into 622e5e6...). Production and tests compiled, ETL passed, and CDC ran 107 tests with exactly the new DLT test failing and zero test errors/skips. The failed assertion found kafka_dlt-exception-message, whose payload carried the credential-bearing JDBC diagnostic. The first failing boundary was therefore the intended framework/production dead-letter contract rather than setup/import/fixture code.

GREEN — 58e21a9bda5aa1fe3fa2654f1f70f6c45bd3bbfd

The production fix retains the existing recoverer and destination mapping but excludes only HeadersToAdd.EX_MSG and HeadersToAdd.EX_STACKTRACE. Original record content, source metadata and finite exception class/cause classification remain available for the current recovery model. No regex masking, truncation or alternate storage path is introduced. KafkaConfig and both public bean factory methods also document the dead-letter privacy/recovery boundary in beginner-readable Javadoc.

CI 31347862962 completed successfully on macOS, Ubuntu and Windows. macOS job 93333070863 checked out synthetic merge 910958c403635583ce2c353f04d033741cb6114e, ran KafkaConfigTest 6/6 green, CDC 107/107 green, ETL 275/275 green, gateway tests green, and completed the full reactor with BUILD SUCCESS.

The same CI job independently reproduces the inherited protected JaCoCo defect: report and check each say Analyzed bundle 'etl-service' with 0 classes and then report the coverage checks met. #162/#164 owns that root-cause repair; this CI result is not non-vacuous 100% owned-production coverage evidence.

The current protected CI workflow also checked out the GitHub PR merge ref, not literal source head 58e21a9...; the successful CI aggregate is integration-tree behavior evidence, not accepted literal-source proof.

Security Scan completeness RCA — aggregate green is not accepted evidence

Security Scan 31347862957 completed with aggregate success, but the hard Trivy filesystem job 93333070855 is not accepted as a complete vulnerability gate for two independent reasons:

  1. it checked out synthetic merge 910958c403635583ce2c353f04d033741cb6114e, not literal source head 58e21a9...; and
  2. Trivy printed Dependency version cannot be determined. Child dependencies will not be found. before reporting 0 CRITICAL/HIGH/MEDIUM findings.

Issue #196 now owns this scanner-completeness defect. A zero-findings SARIF cannot prove absence of vulnerable BOM-managed Maven dependencies when the scanner itself states dependency resolution is incomplete. The current result is therefore incomplete / non-passing under mightyETL acceptance despite the aggregate green conclusion.

This does not supersede shared Jackson remediation #160. The protected dependency baseline still requires resolved same-revision advisory evidence; one incomplete Trivy run cannot establish that the inherited Jackson line is clean. Do not duplicate #160's BOM change here, suppress the scanner warning, add an ignore, reduce severity, or treat another scanner as an automatic substitute without proving same-revision completeness.

Current gate state

For exact source head 58e21a9bda5aa1fe3fa2654f1f70f6c45bd3bbfd:

Documentation / data-governance boundary

This slice closes only raw exception diagnostic transport in DLT headers. #181 still owns the larger production decision for payload/header data classification, broker retention, tenant/owner access, encryption and key ownership, deletion, replay/redrive authorization, schema/version compatibility, poison-message handling, audit evidence, recovery testing and operator runbooks. Canonical PRD/TRD/Architecture/UML/security/data-governance/traceability should reconcile this active_pr only when the #149 documentation writer lane is safe; nothing here is implemented_on_develop before protected integration.

Merge boundary

Keep Draft. Do not merge until the unchanged exact source head has accepted literal-source CI/security evidence under integrated controls, complete same-revision dependency/vulnerability evidence with no unresolved scanner-completeness gap, non-vacuous owned-production coverage under #162/#164 or an equivalent accepted repair, every current dependency/SBOM/SAST/security gate passes, zero valid unresolved review findings remain, and qualifying independent non-author approval exists where governance requires it. No predecessor-head, other-PR, status-only, skipped-required, pending, incomplete-scanner, or synthetic-merge-only evidence transfers into that decision.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7129ff8a-7ed7-435b-beb2-fd0e287db484

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant