Skip to content

refactor(observability): give the payload boundary its own module - #152

Merged
kl3inIT merged 1 commit into
mainfrom
refactor/observability-boundary-module
Jul 30, 2026
Merged

refactor(observability): give the payload boundary its own module#152
kl3inIT merged 1 commit into
mainfrom
refactor/observability-boundary-module

Conversation

@kl3inIT

@kl3inIT kl3inIT commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Closes the last open decision of the observability increment — and investigating
it found that one deployable had no payload boundary at all.

What was wrong

integrations/graph-rag-observability opens with
api(project(":components:graph-rag-core")). Taking the payload boundary meant
taking the graph domain.

apps/mcp did not take it. Its build file had no project(...) dependency at
all
— the only Gradle application here with none — while carrying
spring-boot-starter-opentelemetry and exporting spans.

So the guarantee decision 0018
states across the process held in two deployables and in none of the third's
spans. KnowledgeSearchApiClient chains a RestClientException as the cause of
its own constant-message failure, and exception.stacktrace exports unfiltered
without the sanitizer. Whether any particular exception carried payload was not
established; that nothing would have stopped it was.

Seven of that module's ten files had nothing to do with GraphRAG — two of them
added the same day, by the increment that found this.

The split

Module Holds Depends on
integrations/observability (new) span sanitizer, both startup verifiers no OrgMemory module
integrations/graph-rag-observability the two GraphRagEventSink adapters, the GraphRagTaskDecorator implementation graph-rag-core

The absence of a project(...) line in the new module is load-bearing. It is
what keeps the boundary adoptable by a deployable with no domain dependency —
the condition that failed here.

graph-rag-observability depends on the new module only in its test source
set, where WholeExportAllowlistTests drives a GraphRAG span through the
sanitizer in the position the sanitizer occupies in production. That test
belongs across the seam.

Enforcement, not a name

orgmemory.spring-boot-app-conventions now adds the new module. Taking the
convention is taking the boundary. Every Gradle application already applies that
plugin, so:

apps/mcp runtimeClasspath → project ':integrations:observability'
                          → nothing else

apps/mcp gains the boundary without its own build file changing, still does
not carry graph-rag-core, and a fourth application cannot omit it by not
knowing to ask.

An exception recorded rather than slipped in

ARCHITECTURE.md states the adapter rule as integrations -> core ports. The
new module implements no core port — it implements OpenTelemetry's SpanExporter
and two startup checks that implement nothing. By that rule it is not an
integration.

Placing it in integrations/ anyway is the project owner's decision, taken after
the alternatives were laid out, including a fifth top-level directory that was
rejected as more structure than ~250 lines earns against a module count already
at seventeen. Both ARCHITECTURE.md and
decision 0019
name it as an exception that was seen and chosen.

No behaviour changed

The four boundary test classes moved unedited. 32 + 28 is the 60 the single
module ran before.

:integrations:observability:test              32
:integrations:graph-rag-observability:test    28
:apps:api:test                               152
:apps:worker:test                             47
:apps:mcp:test                                55
                                             314 tests, 0 skipped, 0 failures

Not done here

Decision 0019's challenge — proposal, strongest counterargument, repository
evidence, choice, rejected alternatives — is recorded, but I wrote the
counterargument myself. It has not been through an independent reviewer.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added centralized observability safeguards that automatically sanitize sensitive content and exception details in telemetry.
    • Enabled observability protections across applicable application services by default.
    • Added automatic discovery for telemetry boundary and logging safeguards.
  • Documentation

    • Clarified the system architecture and boundaries for observability integrations.
  • Tests

    • Expanded coverage for content protection, logging safeguards, and telemetry export sanitization.

`integrations/graph-rag-observability` opened with
`api(project(":components:graph-rag-core"))`, so taking the payload boundary
meant taking the graph domain. `apps/mcp` did not take it: its build file had
no `project(...)` dependency at all — the only Gradle application here with
none — while carrying the OpenTelemetry starter and exporting spans. So the
guarantee decision 0018 states across the process held in two deployables and
in none of the third's spans.

Seven of that module's ten files had nothing to do with GraphRAG, two of them
added the same day by the increment that found this.

The boundary moves to `integrations/observability`, which depends on no
OrgMemory module. That absence is load-bearing: it is what keeps the boundary
adoptable by a deployable with no domain dependency, which is the condition
that failed. `graph-rag-observability` keeps what implements a core port — the
two event sinks and the task decorator — and depends on the new module only in
its test source set, where the whole-export allowlist gate drives a GraphRAG
span through the sanitizer in the position it occupies in production.

`orgmemory.spring-boot-app-conventions` adds the new module, so taking the
convention is taking the boundary. `apps/mcp` gains it without its build file
changing, and a fourth application cannot omit it by not knowing to ask.

No behaviour changed and no test was rewritten: the four boundary test classes
moved unedited, and 32 + 28 is the 60 the single module ran before.

`ARCHITECTURE.md` and decision 0019 both record that this module is a
deliberate exception to `integrations -> core ports` — it implements no core
port — so the exception is one that was seen and chosen rather than one that
was never noticed.

Gates: :integrations:observability:test (32),
:integrations:graph-rag-observability:test (28), :apps:api:test (152),
:apps:worker:test (47), :apps:mcp:test (55). 314 tests, 0 skipped, 0 failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0d44e7ec-6a19-46be-9d17-eaaad81d652b

📥 Commits

Reviewing files that changed from the base of the PR and between 27b8fb4 and 4279f81.

⛔ Files ignored due to path filters (5)
  • docs/decisions/0019-the-payload-boundary-is-its-own-module.md is excluded by !docs/**
  • docs/increments/active/2026-07-29-observability-pipeline/plan.md is excluded by !docs/**
  • docs/increments/active/2026-07-30-observability-platform/plan.md is excluded by !docs/**
  • docs/specs/domains/secure-graph-rag.md is excluded by !docs/**
  • docs/tests/domains/secure-graph-rag.md is excluded by !docs/**
📒 Files selected for processing (20)
  • ARCHITECTURE.md
  • apps/api/src/test/java/com/orgmemory/api/observability/ObservationContentBoundaryTests.java
  • apps/worker/src/test/java/com/orgmemory/worker/observability/ObservationContentBoundaryTests.java
  • build-logic/src/main/kotlin/orgmemory.spring-boot-app-conventions.gradle.kts
  • integrations/graph-rag-observability/build.gradle.kts
  • integrations/graph-rag-observability/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  • integrations/graph-rag-observability/src/test/java/com/orgmemory/integrations/graphrag/observability/WholeExportAllowlistTests.java
  • integrations/observability/build.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporter.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryAutoConfiguration.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifier.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryAutoConfiguration.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifier.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfiguration.java
  • integrations/observability/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporterTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifierTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifierTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfigurationTests.java
  • settings.gradle.kts
💤 Files with no reviewable changes (1)
  • integrations/graph-rag-observability/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

**/*: Always read the repository guidance and relevant sections of ARCHITECTURE.md; before changing a domain, read its specification, test-coverage document, and binding decision filenames.
Treat the repository as the engineering system of record; current repository and runtime evidence take precedence over chat or Northstar.
Read docs/guidelines/agent-safety.md before retrieval, AI, MCP, permission, upload, graph, or export work. Never commit secrets or customer data.

Files:

  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifierTests.java
  • integrations/observability/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  • integrations/observability/build.gradle.kts
  • apps/api/src/test/java/com/orgmemory/api/observability/ObservationContentBoundaryTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporterTests.java
  • integrations/graph-rag-observability/src/test/java/com/orgmemory/integrations/graphrag/observability/WholeExportAllowlistTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifierTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifier.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfiguration.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifier.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfigurationTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporter.java
  • build-logic/src/main/kotlin/orgmemory.spring-boot-app-conventions.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryAutoConfiguration.java
  • ARCHITECTURE.md
  • apps/worker/src/test/java/com/orgmemory/worker/observability/ObservationContentBoundaryTests.java
  • settings.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryAutoConfiguration.java
  • integrations/graph-rag-observability/build.gradle.kts
**/*.{java,gradle,gradle.kts,properties,yml,yaml}

📄 CodeRabbit inference engine (CLAUDE.md)

Before using unfamiliar Spring Boot 4, Spring Modulith 2, Spring AI 2, or Gradle APIs, consult current official documentation, Context7, and the relevant project verification skill.

Files:

  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifierTests.java
  • integrations/observability/build.gradle.kts
  • apps/api/src/test/java/com/orgmemory/api/observability/ObservationContentBoundaryTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporterTests.java
  • integrations/graph-rag-observability/src/test/java/com/orgmemory/integrations/graphrag/observability/WholeExportAllowlistTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifierTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifier.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfiguration.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifier.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfigurationTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporter.java
  • build-logic/src/main/kotlin/orgmemory.spring-boot-app-conventions.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryAutoConfiguration.java
  • apps/worker/src/test/java/com/orgmemory/worker/observability/ObservationContentBoundaryTests.java
  • settings.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryAutoConfiguration.java
  • integrations/graph-rag-observability/build.gradle.kts
**/*.{java,sql}

📄 CodeRabbit inference engine (CLAUDE.md)

Keep ddl-auto=validate and pair every persisted-model change with a Flyway migration.

Files:

  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifierTests.java
  • apps/api/src/test/java/com/orgmemory/api/observability/ObservationContentBoundaryTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporterTests.java
  • integrations/graph-rag-observability/src/test/java/com/orgmemory/integrations/graphrag/observability/WholeExportAllowlistTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifierTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifier.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfiguration.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifier.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfigurationTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporter.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryAutoConfiguration.java
  • apps/worker/src/test/java/com/orgmemory/worker/observability/ObservationContentBoundaryTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryAutoConfiguration.java
**/*.{java,gradle,gradle.kts}

📄 CodeRabbit inference engine (CLAUDE.md)

Use the testing harness; a terminating clean test is the JVM context gate, and bootRun is not verification. IDE inspection applies only to edited backend Java.

Files:

  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifierTests.java
  • integrations/observability/build.gradle.kts
  • apps/api/src/test/java/com/orgmemory/api/observability/ObservationContentBoundaryTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporterTests.java
  • integrations/graph-rag-observability/src/test/java/com/orgmemory/integrations/graphrag/observability/WholeExportAllowlistTests.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifierTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifier.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfiguration.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifier.java
  • integrations/observability/src/test/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfigurationTests.java
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporter.java
  • build-logic/src/main/kotlin/orgmemory.spring-boot-app-conventions.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryAutoConfiguration.java
  • apps/worker/src/test/java/com/orgmemory/worker/observability/ObservationContentBoundaryTests.java
  • settings.gradle.kts
  • integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryAutoConfiguration.java
  • integrations/graph-rag-observability/build.gradle.kts
ARCHITECTURE.md

📄 CodeRabbit inference engine (CLAUDE.md)

Keep ARCHITECTURE.md limited to implemented facts, current project-wide facts, and commands; do not use it for intended or unimplemented behavior.

Files:

  • ARCHITECTURE.md
🔇 Additional comments (19)
settings.gradle.kts (1)

32-32: LGTM!

integrations/observability/build.gradle.kts (1)

1-29: LGTM!

integrations/observability/src/main/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporter.java (1)

1-1: LGTM!

build-logic/src/main/kotlin/orgmemory.spring-boot-app-conventions.gradle.kts (1)

13-20: LGTM!

integrations/graph-rag-observability/build.gradle.kts (1)

14-19: LGTM!

integrations/graph-rag-observability/src/test/java/com/orgmemory/integrations/graphrag/observability/WholeExportAllowlistTests.java (1)

7-7: LGTM!

apps/api/src/test/java/com/orgmemory/api/observability/ObservationContentBoundaryTests.java (1)

7-7: LGTM!

apps/worker/src/test/java/com/orgmemory/worker/observability/ObservationContentBoundaryTests.java (1)

7-7: LGTM!

ARCHITECTURE.md (1)

29-30: LGTM!

Also applies to: 50-57

integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryAutoConfiguration.java (1)

1-1: 🗄️ Data Integrity & Integration

No change needed.

integrations/observability/src/main/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifier.java (1)

1-1: LGTM!

integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryAutoConfiguration.java (1)

1-1: LGTM!

integrations/observability/src/main/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifier.java (1)

1-1: LGTM!

integrations/observability/src/main/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfiguration.java (1)

1-1: LGTM!

integrations/observability/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (1)

1-3: LGTM!

integrations/observability/src/test/java/com/orgmemory/integrations/observability/ExceptionSanitizingSpanExporterTests.java (1)

1-1: LGTM!

integrations/observability/src/test/java/com/orgmemory/integrations/observability/ObservationContentBoundaryVerifierTests.java (1)

1-1: LGTM!

integrations/observability/src/test/java/com/orgmemory/integrations/observability/ProviderLoggingBoundaryVerifierTests.java (1)

1-1: LGTM!

integrations/observability/src/test/java/com/orgmemory/integrations/observability/SpanExportSanitizationAutoConfigurationTests.java (1)

1-1: LGTM!


📝 Walkthrough

Walkthrough

The telemetry boundary is extracted into integrations:observability, its classes are repackaged and auto-registered, application conventions add it as an implementation dependency, and GraphRAG retains only its own auto-configuration registration.

Changes

Observability Boundary Extraction

Layer / File(s) Summary
Standalone observability module
settings.gradle.kts, integrations/observability/...
Adds the observability Gradle module, relocates boundary classes and tests to com.orgmemory.integrations.observability, and registers its three auto-configurations.
Application and GraphRAG wiring
build-logic/..., integrations/graph-rag-observability/..., apps/api/..., apps/worker/...
Adds the boundary module through application conventions, removes its auto-configurations from GraphRAG registration, and updates test dependencies and imports.
Boundary dependency documentation
ARCHITECTURE.md
Documents GraphRAG observability and the telemetry payload boundary as separate integrations and records the convention-based adapter exception.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 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 The title clearly summarizes the main refactor: extracting the payload boundary into its own module.
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 refactor/observability-boundary-module

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.

@kl3inIT
kl3inIT merged commit 71d30dd into main Jul 30, 2026
14 checks passed
@kl3inIT
kl3inIT deleted the refactor/observability-boundary-module branch July 30, 2026 16:40
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