Skip to content

fix(security): push analytics tenant isolation into repository query - #342

Closed
seonghobae wants to merge 7 commits into
mainfrom
fix/analytics-tenant-query-main-20260810
Closed

fix(security): push analytics tenant isolation into repository query#342
seonghobae wants to merge 7 commits into
mainfrom
fix/analytics-tenant-query-main-20260810

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Objective

Reconcile the tenant-scoped list-query semantic from stale descendant #268 directly on current protected main and adopt it in analytics so KPI reads never request the global conversion-job inventory and filter ownership afterward.

Fresh exact state — 2026-08-10

  • exact source head: 4eeba73d70db172e44062891c01273efc4109d93;
  • independently resolved protected main: 55d7ae8647208e301f282350f076eeddaba61d11;
  • clean current-base slice: four changed files, six commits, zero commits behind protected main;
  • exact-head CI 31401293063: success;
  • exact-head Security Scan 31401293204: success;
  • exact-head SAST Semgrep 31401293014: success;
  • exact-head fuzz 31401293142: success;
  • authoritative Maven verification on the exact source head ran 500 tests with 0 failures, 0 errors and 0 skips; all JaCoCo coverage checks and public Javadocs passed;
  • no unresolved review threads and no formal reviews at the latest direct refetch;
  • automated checks/statuses are evidence, never qualifying independent approval.

Test-first evidence

RED

Test-only head 0a5ff205b550e2435c4b9267dbc224a2f30e1f02 introduced a focused controller boundary regression before production changes. Exact-head CI 31400542789 checked out that exact SHA and failed during Maven test compilation because protected main did not expose ConversionJobRepository.findAllByTenantId(String). The compiler reported the missing method at all three deliberate test references. Maven merge compatibility and fuzz failed at the same first boundary; buyer-readiness script tests remained green. This established that protected main still required a global inventory read for KPI calculation.

GREEN

Current head adds a fail-closed repository contract whose default returns an empty list rather than falling back to global findAll(). The process-local adapter overrides it with a tenant predicate and rejects missing/blank tenant identifiers. AnalyticsController now passes the authenticated tenant directly into findAllByTenantId(...) and no longer materializes global job inventory.

Focused tests prove:

  • analytics calls the storage-scoped tenant query and never global findAll();
  • authorization failure occurs before either repository query;
  • the interface default fails closed without global fallback;
  • the in-memory adapter rejects null/blank tenant identifiers, normalizes surrounding whitespace and returns only owned jobs.

Exact-head CI also proves synthetic-merge compatibility, packaging, the complete Java test suite, exact owned coverage and public Javadocs. Security Scan, Semgrep and fuzz are GREEN on the unchanged exact head.

Scope boundary

This is a deliberate current-base reconciliation of one valuable #268 semantic plus issue #326 analytics adoption. It does not copy #268's stale ancestry or claim the whole descendant is reconciled. Immutable identifier/tombstone behavior, scoped retry/mutation, durable deletion receipts/recovery, audit pseudonymization and generation fencing remain separate semantics to preserve or reimplement deliberately. It is path-disjoint from #341's administrative delete endpoint and from #338/#339 KPI formula/ledger semantics.

Merge gate

Move to Ready for ordinary independent review. Keep this exact head unchanged. Merge or auto-merge may complete only after live protection still sees all applicable required checks passing, zero valid unresolved findings, and any required qualifying independent non-author approval. Automated evidence is not approval.

Summary by CodeRabbit

  • 개선 사항

    • 분석 KPI 조회가 테넌트별 작업만 대상으로 처리되도록 개선되었습니다.
    • 유효하지 않거나 공백인 테넌트 정보에는 빈 결과가 반환됩니다.
    • 분석 권한이 없으면 불필요한 작업 조회를 수행하지 않습니다.
  • 테스트

    • 테넌트 간 데이터가 섞이지 않는지와 권한별 조회 동작을 검증하는 테스트가 추가되었습니다.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e68ff9b-a0b6-4ab8-8fff-080d4e90c36c

📥 Commits

Reviewing files that changed from the base of the PR and between b66b692 and f890410.

📒 Files selected for processing (4)
  • src/main/java/com/clearfolio/viewer/controller/AnalyticsController.java
  • src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java
  • src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java
  • src/test/java/com/clearfolio/viewer/controller/AnalyticsTenantQueryBoundaryTest.java

📝 Walkthrough

Walkthrough

분석 KPI 조회가 전체 작업 조회 후 필터링하는 방식에서 테넌트 범위 저장소 조회 방식으로 변경되었습니다. 저장소 계약과 인메모리 구현을 추가했으며, 권한 및 테넌트 경계 조건을 테스트합니다.

Changes

테넌트 범위 분석 조회

Layer / File(s) Summary
테넌트 범위 저장소 조회
src/main/java/com/clearfolio/viewer/repository/ConversionJobRepository.java, src/main/java/com/clearfolio/viewer/repository/InMemoryConversionJobRepository.java
findAllByTenantId 저장소 메서드를 추가했습니다. 인메모리 구현은 tenant ID를 정규화하고 일치하는 작업만 반환합니다.
분석 KPI 조회 연결 및 검증
src/main/java/com/clearfolio/viewer/controller/AnalyticsController.java, src/test/java/com/clearfolio/viewer/controller/AnalyticsTenantQueryBoundaryTest.java
kpiSnapshot이 테넌트 범위 조회를 사용합니다. 테스트는 전역 조회 폴백, 권한 없는 조회, 누락·공백 tenant ID를 검증합니다.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • ContextualWisdomLab/clearfolio 이슈 326: 분석 KPI 조회에 테넌트 격리를 적용하는 변경과 직접 연결됩니다.

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AnalyticsController
  participant ConversionJobRepository
  participant KPIRegister
  Client->>AnalyticsController: KPI snapshot request
  AnalyticsController->>ConversionJobRepository: findAllByTenantId(tenantId)
  ConversionJobRepository-->>AnalyticsController: tenant-scoped ConversionJob list
  AnalyticsController->>KPIRegister: build KPI snapshot
  KPIRegister-->>Client: KPI snapshot response
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 분석 KPI 조회에 테넌트 격리를 저장소 쿼리로 적용하는 주요 변경을 정확하고 간결하게 설명합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/analytics-tenant-query-main-20260810

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.

Copy link
Copy Markdown
Collaborator Author

Superseded by #432. Fresh reconstruction proved #342 had diverged one commit behind protected main; #432 is built directly on 961f44a19c4ced87f8062b3ab9842a9a08d05235, is one commit ahead/zero behind, and preserves exactly the four unique #342 file deltas while retaining the current protected-main #276 security change. No review threads or formal reviews were lost. Fresh exact-head gates must be regenerated on #432; no predecessor evidence transfers.

@seonghobae seonghobae closed this Aug 13, 2026
auto-merge was automatically disabled August 13, 2026 05:15

Pull request was closed

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