Skip to content

fix(worker): decrypt CRM regulatory_fields + related_parties PII - #318

Merged
brunobls merged 2 commits into
developfrom
fix/crm-regulatory-fields-decryption
Jul 15, 2026
Merged

fix(worker): decrypt CRM regulatory_fields + related_parties PII#318
brunobls merged 2 commits into
developfrom
fix/crm-regulatory-fields-decryption

Conversation

@brunobls

Copy link
Copy Markdown
Member

Description

Adds decryption for two CRM PII fields on the plugin_crm extraction path (Worker) that were previously projected into the snapshot as ciphertext:

  • regulatory_fields.participant_document (a CNPJ) — new decryptRegulatoryFields
  • related_parties[].document — new decryptRelatedParties (slice-shaped)

Both mirror the existing per-object decryptors, reuse the same *libCrypto.Crypto instance, and are wired into decryptNestedFields. name / role / dates stay plaintext.

Why: this ciphertext-in-snapshot gap is the root cause of CCS-0011 in br-ccs batch generation — br-ccs received an encrypted CNPJ where it expected a plaintext value. plugin_crm bypasses pkg/engine and runs the legacy extract_crm_data.go path, so the fix is local to that file.

Verified against the live dev-st CRM (midaz-crm, KMS_VENDOR=none): 15/15 participant_document and 15/15 related_parties[].document are legacy AES-GCM (0 tink:-format), decryptable with the key the Fetcher already holds. Fail-closed on undecryptable values; errors name the field/index, never the raw value (no PII in logs/errors).

Type of Change

  • fix: Bug fix

Breaking Changes

None.

Testing

  • make test passes
  • make lint passes
  • make sec passes (full monorepo, exit 0)
  • make test-int — n/a (no integration paths exercised by this change)

Also green: go build ./..., gofmt, -race on the changed package; coverage 87.3%. make vulncheck (trivy) runs in CI.

Test evidence: Gate 0 TDD RED→GREEN per task; Gate 8 review — Epic 1.1 (regulatory_fields) 9/9 reviewers, Epic 2.1 (related_parties) focused 5-reviewer pool; cycle-close /code-review (high) + whole-diff HIGH-effort + /go-comment-reviewer.

Architectural Checklist

  • No panic() in production paths
  • Errors wrapped with %w
  • Timestamps use time.Now().UTC() (n/a — no timestamps added)
  • Handlers stay thin / infra in internal/bootstrap (n/a — Worker decrypt path, not HTTP handlers)

Related Issues

Root cause of CCS-0011 in br-ccs batch generation (no GitHub issue tracked; see fetcher-033).

Follow-ups (not in this PR)

  • Per-record failure isolation in the decryptPluginCRMData loop (one undecryptable record currently fails the whole collection — intentional fail-closed for now).
  • tink:-format handling (other CRM orgs use Tink in the write path).
  • Whitelist-coverage audit + anti-regression guard (plan Epic 2.2).
  • Cleanups: generalize the per-object/slice decryptors into one table-driven helper; extract a newTestCrypto(t) helper; split the oversized extract_crm_data_test.go.

The plugin_crm extraction path decrypted contact, banking_details, legal_person and natural_person fields but not regulatory_fields or related_parties, so participant_document (a CNPJ) and related_parties[].document were projected as ciphertext into the snapshot -- the root cause of CCS-0011 in br-ccs batch generation.

Add decryptRegulatoryFields and decryptRelatedParties, mirroring the existing per-object decryptors and reusing the same crypto instance; wire both into decryptNestedFields. Verified against the live dev-st CRM (KMS_VENDOR=none): all values are legacy AES-GCM (no tink: format). Fail-closed on undecryptable values; name/role/dates stay plaintext.

X-Lerian-Ref: 0x1
@brunobls
brunobls requested a review from a team as a code owner July 15, 2026 16:25
@lerian-studio

Copy link
Copy Markdown
Contributor

Lerian Library Version Check

Library Current Latest Status
lib-auth/v2 v2.9.0 v2.9.0 Current
lib-commons/v5 v5.10.0 v5.10.0 Current
lib-observability v1.1.0 v1.1.0 Current
lib-streaming v1.8.0 v1.8.0 Current
fetcher/pkg/engine v1.1.0-beta.1 skipped Skipped (ignore file)

0 outdated | 4 current | 1 skipped | 0 unknown

@lerian-studio lerian-studio added the size/L PR changes 500-999 lines label Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Plugin CRM nested decryption now handles regulatory_fields.participant_document and related_parties[].document. Invalid targeted ciphertext returns contextual errors without exposing ciphertext, while absent or malformed containers remain no-op paths. Tests add real-crypto coverage for success, edge cases, and fail-fast behavior.

Changes

CRM nested decryption

Layer / File(s) Summary
Nested decryption flow
components/worker/internal/services/extract_crm_data.go
decryptNestedFields now decrypts regulatory participant documents and related-party documents through dedicated helpers with contextual error wrapping.
Regulatory field validation
components/worker/internal/services/extract_crm_data_test.go
Tests cover regulatory-field decryption, absent or malformed data, invalid ciphertext, and integration with plugin CRM fixtures.
Related-party document validation
components/worker/internal/services/extract_crm_data_test.go
Tests cover slice-element decryption, skipped entries, indexed errors, ciphertext sanitization, and fail-fast processing.

Sequence Diagram(s)

sequenceDiagram
  participant CRMRecord
  participant decryptNestedFields
  participant decryptRegulatoryFields
  participant decryptRelatedParties
  participant decryptFieldValue
  CRMRecord->>decryptNestedFields: provide nested fields
  decryptNestedFields->>decryptRegulatoryFields: process regulatory_fields
  decryptRegulatoryFields->>decryptFieldValue: decrypt participant_document
  decryptNestedFields->>decryptRelatedParties: process related_parties
  decryptRelatedParties->>decryptFieldValue: decrypt each document
  decryptNestedFields-->>CRMRecord: return updated record or contextual error
Loading

Possibly related PRs

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/crm-regulatory-fields-decryption

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

@lerian-studio lerian-studio added component: worker Worker component area: tests Unit, integration and end-to-end tests labels Jul 15, 2026
@lerian-studio

lerian-studio commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Validation Summary

✅ PR Mergeable — no blocking failures

Check Status Blocking
Source Branch ✅ success yes
PR Title ✅ success yes
PR Description ✅ success yes
PR Size ✅ success no
Auto Labels ✅ success no
PR Metadata ✅ success no

🔍 View workflow run

@lerian-studio

lerian-studio commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🔒 Security Scan Results — manager

✅ PR Mergeable — no blocking findings

Stage Status Blocking?
Filesystem Scan ✅ Clean
Docker Image Scan ✅ Clean
Docker Hub Health Score ✅ Clean
Pre-release Version Check ⚠️ 1 finding 🟡 No (advisory)

Trivy

Filesystem Scan

✅ No vulnerabilities or secrets found.

Docker Image Scan

✅ No vulnerabilities found.


Docker Hub Health Score Compliance

✅ Policies — 4/4 met

Policy Status
Default non-root user ✅ Passed
No fixable critical/high CVEs ✅ Passed
No high-profile vulnerabilities ✅ Passed
No AGPL v3 licenses ✅ Passed

Pre-release Version Check

🚫 Found 1 unstable version pin(s). Only stable releases (x.y.z) and SHA-based pins are allowed.

File Line Content
./go.mod 68 github.com/LerianStudio/fetcher/pkg/engine v1.1.0-beta.1

Replace pre-release suffixes (-alpha, -beta, -rc, -dev, etc.) with stable releases.


🔍 View full scan logs

@lerian-studio

Copy link
Copy Markdown
Contributor

📊 Unit Test Coverage Report: fetcher-manager

Metric Value
Overall Coverage 89.7% ✅ PASS
Threshold 80%

Coverage by Package

Package Coverage
github.com/LerianStudio/fetcher/v2/components/manager/cmd/huma-spec 33.4%
github.com/LerianStudio/fetcher/v2/components/manager/internal/adapters/cache 100.0%
github.com/LerianStudio/fetcher/v2/components/manager/internal/adapters/http/in 89.4%
github.com/LerianStudio/fetcher/v2/components/manager/internal/services/command 92.8%
github.com/LerianStudio/fetcher/v2/components/manager/internal/services/query 96.4%

Generated by Go PR Analysis workflow

@lerian-studio

Copy link
Copy Markdown
Contributor

📊 Unit Test Coverage Report: fetcher-worker

Metric Value
Overall Coverage 87.4% ✅ PASS
Threshold 80%

Coverage by Package

Package Coverage
github.com/LerianStudio/fetcher/v2/components/worker/internal/services 90.0%

Generated by Go PR Analysis workflow

@lerian-studio

lerian-studio commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🔒 Security Scan Results — worker

✅ PR Mergeable — no blocking findings

Stage Status Blocking?
Filesystem Scan ✅ Clean
Docker Image Scan ✅ Clean
Docker Hub Health Score ✅ Clean
Pre-release Version Check ⚠️ 1 finding 🟡 No (advisory)

Trivy

Filesystem Scan

✅ No vulnerabilities or secrets found.

Docker Image Scan

✅ No vulnerabilities found.


Docker Hub Health Score Compliance

✅ Policies — 4/4 met

Policy Status
Default non-root user ✅ Passed
No fixable critical/high CVEs ✅ Passed
No high-profile vulnerabilities ✅ Passed
No AGPL v3 licenses ✅ Passed

Pre-release Version Check

🚫 Found 1 unstable version pin(s). Only stable releases (x.y.z) and SHA-based pins are allowed.

File Line Content
./go.mod 68 github.com/LerianStudio/fetcher/pkg/engine v1.1.0-beta.1

Replace pre-release suffixes (-alpha, -beta, -rc, -dev, etc.) with stable releases.


🔍 View full scan logs

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/worker/internal/services/extract_crm_data.go`:
- Around line 589-617: Extract the repeated map-container field decryption flow
into a shared helper, then update decryptRegulatoryFields and
decryptBankingDetailsFields (plus the existing contact sibling if applicable) to
use it. The helper should type-assert the nested map, iterate the supplied field
names, call decryptFieldValue, wrap errors with the nested field context, and
write the updated map back while preserving current behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 45bbc56c-38de-4cd9-a226-42b9cf35795c

📥 Commits

Reviewing files that changed from the base of the PR and between 4a64601 and 822dee7.

📒 Files selected for processing (2)
  • components/worker/internal/services/extract_crm_data.go
  • components/worker/internal/services/extract_crm_data_test.go

Comment thread components/worker/internal/services/extract_crm_data.go
@brunobls
brunobls merged commit b33c845 into develop Jul 15, 2026
32 checks passed
@github-actions
github-actions Bot deleted the fix/crm-regulatory-fields-decryption branch July 15, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: tests Unit, integration and end-to-end tests component: worker Worker component size/L PR changes 500-999 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants