Skip to content

docs: ADR-0032 — exception handling, logging, observability foundation - #2

Merged
cemililik merged 6 commits into
mainfrom
feat/phase-01-infra-identity-eventing
May 19, 2026
Merged

docs: ADR-0032 — exception handling, logging, observability foundation#2
cemililik merged 6 commits into
mainfrom
feat/phase-01-infra-identity-eventing

Conversation

@cemililik

@cemililikcemililik commented May 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • ADR-0032 + Architecture 33: binding cross-cutting contract for error
    handling, logging, and observability before Phase 02a opens — 13
    sub-decisions, no code (repo is pre-implementation).
  • Closes the Standards 02 ↔ Standards 09 ↔ ADR-0016 pipeline-order +
    exception-catch gap, plus 11 previously-unwritten implementation
    details (IExceptionHandler choice, ValidationBehavior throw-vs-return,
    DomainException semantics, Polly v8 IProviderResilience<TPort>,
    Result<T>.ToActionResult() mapping, Sentry-vs-OTel boundary, Serilog
    primary + OTLP sink, TenantContextSpanProcessor via
    ITenantContextAccessor, IErrorTrackingProvider deployment-mode
    branching, Hub /api/internal/*traceparent propagation, outbox +
    Hangfire correlation columns, frontend Sentry correlation handoff).
  • Two new skills (wire-cross-cutting-foundation, add-provider-adapter)
    plus add-mediatr-handler update so Phase 02a engineers don't
    re-derive the contract.

Scope

  • NEW: docs/decisions/0032-exception-handling-logging-and-observability.md,
    docs/architecture/33-cross-cutting-concerns.md,
    .claude/skills/wire-cross-cutting-foundation/SKILL.md,
    .claude/skills/add-provider-adapter/SKILL.md.
  • MODIFIED (cross-link / amendment / forbidden-list / deliverable
    alignment): Standards 02 / 09 / 10 / 20, roadmap phase-02a + phase-02b,
    glossary, decisions/README, CLAUDE.md, skills/README,
    add-mediatr-handler skill, plus a leftover Dapr README polish (f391b4f)
    that was sitting on the branch from PR feat(infra): Phase 01 packets 4-6 + ADRs 0029-0031 backend swap #1's third review round.
  • No code changes — repo is pre-implementation (only Result<T> +
    Error records exist as live code under
    backend/src/LearnStack.SharedKernel/Results/); ADR-0032 lands as
    contract for Phase 02a / 02b to implement.

Test plan

Pure-documentation PR. Verification done before this PR was opened:

  • Markdown broken-link audit across all 12 modified + 4 new files —
    every relative target resolves.
  • ADR-0032 template compliance — Status / Date / Deciders /
    Decision Drivers / Considered Options (3 rejected alternatives with
    concrete "why rejected") / Decision / Context / Consequences
    (Positive / Negative / Neutral) / Implementation Notes / References.
  • Cross-doc consistency — pipeline order matches verbatim across
    ADR-0016 / ADR-0032 / Standards 02.
  • ADR-0016 immutability respected — its Decision section is not
    amended; ADR-0032 cites and extends.
  • docs/analysis/ residual scan — clean (only the hard-rule
    reference in CLAUDE.md, which is the rule itself).
  • decisions/README.md active-ADR table includes row 0032; reserved
    draft slots 0023-0028 untouched.
  • Architecture-test names follow the project's Subject_Constraint
    convention (MediatR_Pipeline_Order_Matches_Canonical_Sequence, …) —
    no ADR number baked into a test identifier.
  • Glossary additions are tabled under "Cross-Cutting Concerns" with
    one-line definitions linking back to ADR-0032 / Standards 09 / 10.
  • Code-review-agent pass walked + 9 of 10 findings addressed (1
    intentional skip noted in commit d6cdba8).

To verify after merge (Phase 02a)

  • LearnStackExceptionHandler : IExceptionHandler ships with the
    ShouldCapture(ex) switch behaviour matching the partition table.
  • MediatR pipeline DI registration order matches the canonical
    8-step list; architecture test MediatR_Pipeline_Order_Matches_Canonical_Sequence
    is green and non-skippable.
  • ITenantContextAccessor (singleton, AsyncLocal<ITenantContext?>-backed)
    ships in LearnStack.SharedKernel; populated at scope start by every
    surface listed in ADR-0032 § Sub-decision 10.
  • Roslyn analyzer LearnStackException-DomainExceptionThrow is
    referenced by Domain + Application projects (Warning in
    Phase 02a, Error after Phase 03 exit).
  • IErrorTrackingProvider composition-root branching emits the
    right implementation per DeploymentMode;
    LocalFileErrorTracker is used in SelfHostedAirGapped.

Notes for reviewers

  • This ADR is large by design — it codifies thirteen sub-decisions in
    one place so the standards and roadmap can cite it instead of restating
    the rules. The Considered Options section explains why a single ADR
    (Option A) was preferred over the alternatives (multi-ADR split,
    amending ADR-0016, deferring to Phase 02a code review).
  • The previous PR's third-round commit (f391b4f) is included here
    because it never made it onto the merged PR feat(infra): Phase 01 packets 4-6 + ADRs 0029-0031 backend swap #1; it's a Dapr README
    clarity polish unrelated to ADR-0032 but small enough to ride along.
  • Phase 02a roadmap deliverables list now references this ADR for every
    cross-cutting concern; Phase 02b references it for outbox / Hangfire
    correlation columns. No code change in either phase from this PR.

🤖 Generated with Claude Code

Summary by Sourcery

Document the cross-cutting backend contract for exception handling, logging, and observability and align existing standards, roadmap, glossary, skills, and infra docs with ADR-0032, without changing any runtime code.

Enhancements:

  • Define the canonical MediatR pipeline order, L1 exception handling via IExceptionHandler, Result.ToActionResult mapping, and DomainException usage rules, and reflect them across backend coding standards and skills.
  • Establish the Sentry vs OpenTelemetry error-capture boundary, Serilog-as-primary logging pattern, tenant correlation span enrichment via TenantContextSpanProcessor, and deployment-mode-specific IErrorTrackingProvider behavior in observability standards and infrastructure docs.
  • Introduce ADR-0032 and a new cross-cutting architecture doc consolidating error handling, logging, tracing, metrics, provider resilience via IProviderResilience, and correlation propagation across HTTP, outbox, Hangfire, and Hub surfaces.
  • Extend roadmap phases 02a/02b with concrete cross-cutting deliverables and architecture tests, and update glossary and CLAUDE guardrails to embed the new cross-cutting terminology and forbidden patterns.
  • Clarify Dapr dev setup, phase ownership of Dapr-backed adapters, and Coturn configuration deferral in infra docs to match the updated cross-cutting and phase-planning model.

Documentation:

  • Add ADR-0032 and architecture doc 33-cross-cutting-concerns to define the unified design for exception handling, logging, observability, provider resilience, and correlation propagation.
  • Update standards 02, 09, 10, 12, and 20 plus roadmap phase-02a/02b, glossary, and CLAUDE.md to reference ADR-0032 and codify the new cross-cutting rules and terminology.
  • Document new internal skills wire-cross-cutting-foundation and add-provider-adapter, and refine the add-mediatr-handler skill to match the canonical pipeline and error-handling model.
  • Improve infra docs for Dapr and Coturn to clarify phase ownership, runtime wiring, and dev-topology diagrams without changing behavior.

Tests:

  • Describe and reference new and updated architecture and analyzer tests that will enforce the pipeline order, error-handling discipline, provider exception wrapping, tenant context span enrichment, and deployment-specific error tracking once implementation lands.

Summary by CodeRabbit

  • Documentation
    • Added comprehensive architecture standards for exception handling, logging, and observability patterns.
    • Documented canonical cross-cutting foundation wiring patterns and provider adapter resilience guidelines.
    • Established architecture test catalogue as the authoritative reference for backend compliance rules.
    • Updated roadmap and infrastructure documentation to align with new standards.

Review Change Stack

cemililikand others added 3 commits May 20, 2026 01:01
Three round-3 nitpicks against the Phase 01 packets 4-6 surface.
infra/dapr/README.md:
- Phase-assignment ambiguity. The building-blocks table said `ICacheService`
/ `ISecretProvider` ship in 02a but `IEventBus` in 02b, while a later
paragraph claimed all three Dapr-backed implementations ship in 02b. The
canonical answer (per phase-02a § Shared Kernel + § Dapr Building Blocks)
is that ALL three interfaces AND their Dapr-backed implementations ship
in 02a; only the OutboxProcessor (the consuming call site for IEventBus)
waits until 02b. Replaced the per-row "(Phase 02a/02b)" hint with a
dedicated phase-ownership block and corrected the trailing paragraph.
- Sidecar-topology ASCII art replaced with a Mermaid `graph LR` block per
CLAUDE.md hard rule (diagrams use Mermaid; text fallback retained for
non-Mermaid renderers per the same rule).
infra/coturn/turnserver.conf:
- The deliberate omission of `external-ip`, the still-absent
`rtc.turn_servers` block in livekit.yaml, and the static
user/secret pair are all Phase 08c work. Added a "DEFERRED to Phase 08c"
header pointing at the three concrete follow-ups (external-ip injection,
livekit-side turn_servers wiring, ILiveClassProvider per-session
credential minting via `use-auth-secret`).
docs/standards/12-infrastructure.md:
- MD040: the two service-list fenced code blocks were unmarked. Added
the `text` language identifier to both so the standard renders
consistently and the markdown linter is happy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codifies the pre-implementation cross-cutting foundation as a single binding
contract. Thirteen sub-decisions close the gap between Standards 02 ↔ 09 ↔ 10
and ADR-0016's pipeline-order rule, the Sentry/OTel ambiguity, the
Serilog/OTel double-export risk, tenant.id propagation, deployment-mode-aware
error tracking, the provider resilience pattern, and controller Result
mapping.
Key bindings:
- 8-step MediatR pipeline (Validation → Logging → AuditLog → TenantContext →
Authorization → Transaction → OutboxFlush → Handler). No ExceptionHandlingBehavior.
- IExceptionHandler (.NET 8+) as L1; ValidationBehavior returns
Result.Fail(validation_failed) and never throws.
- DomainException reserved for programmer errors; expected business-rule
violations return Result.Fail(business_rule_violation). Roslyn analyzer
flags violations.
- IProviderResilience<TPort> decorator with Polly v8 ResiliencePipeline
(retry + circuit breaker + timeout + bulkhead) per
appsettings.Resilience:<port>: section.
- Sentry vs OTel error capture partitioned via ShouldCapture(ex): bugs +
5xx provider exceptions go to Sentry; Result.Fail + 4xx provider + cancel
do not.
- Serilog primary logger; OTLP sink to OTel Collector;
AddOpenTelemetry().WithLogging() deliberately not registered alongside.
- TenantContextSpanProcessor enriches every span (auto-instrumented + manual)
with tenant.id / organization.id / user.id / module / correlation.id.
- IErrorTrackingProvider socket branches on DeploymentMode (NoOp / Sentry /
LocalFile); air-gapped Self-Hosted gets the local-file tracker.
- W3C traceparent threads through HTTP + outbox rows + Hangfire payloads +
Hub /api/internal/* envelopes; correlation continues across async
boundaries.
Changes:
- NEW: docs/decisions/0032-exception-handling-logging-and-observability.md
- NEW: docs/architecture/33-cross-cutting-concerns.md (conceptual deep dive,
diagrams)
- NEW: .claude/skills/wire-cross-cutting-foundation/SKILL.md (Phase 02a
one-time foundation wiring)
- NEW: .claude/skills/add-provider-adapter/SKILL.md (canonical pattern for
every new adapter)
- Standards 02 § Pipeline Behaviors rewritten to match ADR-0032 + ADR-0016.
- Standards 09 gains L1, Sentry/OTel boundary, validation Result-not-throw,
DomainException disciplina, provider resilience, controller Result mapping.
- Standards 10 gains Serilog primary, IErrorTrackingProvider table, tenant.id
auto-enrichment, Hub correlation, outbox/job correlation references.
- Standards 20 adds IErrorTrackingProvider + OTLP exporter rows to the
composition-root deployment-mode table; forbidden list adds direct
Sentry.SentrySdk.
- Roadmap phase-02a § Cross-cutting Concerns (Day 1) lists every deliverable
+ ten new architecture tests; phase-02b cites ADR-0032 for outbox /
Hangfire correlation.
- Glossary adds Result<T>, Error, Pipeline Behavior, IExceptionHandler,
Correlation ID, Telemetry Signal, IErrorTrackingProvider,
IProviderResilience<TPort>, TenantContextSpanProcessor,
ProviderException.IsClientError, L1/L2/L3 cache.
- decisions/README.md active-ADR table gains row 0032.
- CLAUDE.md "Things to never do" gains six rules derived from ADR-0032.
- add-mediatr-handler skill updated to reference the canonical pipeline
order and the bug-only DomainException rule.
- skills/README.md catalogue gains the two new skills.
No code changes — repository is pre-implementation; only Result<T> and Error
records exist in backend/src/LearnStack.SharedKernel/Results/ already. The
contract above lands during Phase 02a.
ADR: 0032
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…estion
Code-review agent flagged eight findings on bb0cf16 (ADR-0032 +
cross-cutting concerns). Aksiyon haritası:
Major
-----
- Major #1: TenantContextSpanProcessor would fail at startup with
"Cannot consume scoped service ITenantContext from singleton" if the
constructor takes the request-scoped ITenantContext directly. Introduce
ITenantContextAccessor (singleton, AsyncLocal<ITenantContext?>-backed,
analogous to IHttpContextAccessor). The scoped interface remains for
handler-facing code; the singleton accessor is what cross-cutting
infrastructure (OTel processor, Serilog enricher, Sentry enricher)
reads. The accessor is set at scope start by TenantResolverMiddleware,
HubCorrelationMiddleware, Hangfire JobActivator, and the outbox / inbox
handler scope. Phase 02a ships both contracts together. Updated:
ADR-0032 § Sub-decision 10 + § Implementation Notes (TenantContextSpanProcessor
shape), wire-cross-cutting-foundation skill (new Step 4 + accessor pattern),
Standards 10 § Span Attributes, Phase 02a roadmap deliverables,
Architecture 33 § Tracing Stack, glossary entry.
- Major #2: ADR-0032 § Sub-decision 5 originally listed "Hub HTTP clients"
among IProviderResilience<TPort>-wired adapters and carried a
Resilience.hub: row in the appsettings example. The new
add-provider-adapter skill correctly excludes Hub adapters because they
have an additional mTLS + signed JWT + HMAC wrapper per ADR-0019. The
two documents disagreed. Resolve by removing "Hub HTTP clients" from
the adapter list and dropping the appsettings example row — Hub
adapters get their resilience inside the ADR-0019 wrapper, defined when
the Hub adapter itself lands in Phase 02c.
Minor
-----
- Minor #3: Standards 09 introductory Mermaid diagram still labelled
"Global exception middleware" — replaced with "L1 IExceptionHandler"
to match the rewritten section below.
- Minor #4: "(200 OK on response = success at runtime)" parenthetical in
the Sentry/OTel partition table conflated HTTP status (Result.Fail
returns 4xx) with OTel ActivityStatusCode. Reworded to "runtime
completed; HTTP response is the appropriate 4xx Problem Details".
- Minor #5: Standards 09 listed a custom UnreachableException subclass
that collides with System.Diagnostics.UnreachableException (.NET 7+).
Dropped the subclass; standardized on the BCL type. Skill snippet
qualified.
- Minor #6: ADR-0032 was missing the Deciders: line that ADR-0029/30/31
carry. Added "@platform".
- Minor #8: Standards 10 § Correlation table omitted organization_id
even though sub-decision 10 binds the processor to enrich every span
with it. Added the row, cited ADR-0017.
- Minor #9: The eight-row Sentry/OTel partition table was duplicated in
ADR-0032 § Sub-decision 7 and Standards 09 § Sentry vs OpenTelemetry.
Two copies will drift. Kept the authoritative table in Standards 09;
ADR-0032 now carries a compact summary and cites the standard.
Suggestion
----------
- Suggestion #10: Renamed the architecture test
Pipeline_Order_Matches_ADR_0032 → MediatR_Pipeline_Order_Matches_Canonical_Sequence
in all five reference sites (ADR-0032, wire-cross-cutting-foundation,
glossary, phase-02a roadmap, Standards 02). The ADR citation moves to
the test's [Description] attribute at implementation time. Embedding
the ADR number in the assembly-level identifier would bake a version
into the test name; the Subject_Constraint naming form already used by
the rest of the architecture-test set (Modules_Do_Not_Reference_DeploymentMode,
Every_TenantOwned_Command_HasAuditCoverage) is the correct pattern.
Not addressed (intentional)
---------------------------
- Minor #7: The prior commit body (bb0cf16) understated the CLAUDE.md
rule count ("six" vs eight added). The body is the durable record;
amending it would rewrite history. Noted here for future readers.
ADR: 0032
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sourcery-ai

sourcery-aiBot commented May 19, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduces ADR-0032 and an associated architecture doc to define the cross-cutting contract for exception handling, logging, and observability, then aligns standards, roadmap docs, glossary, skills, and infra readmes around a canonical MediatR pipeline, L1 exception handler, provider resilience pattern, tenant-context tracing enrichment, and deployment-mode-specific error tracking—all without changing runtime code.

File-Level Changes

ChangeDetailsFiles
Add ADR-0032 plus a cross-cutting architecture doc that codify the exception-handling, logging, tracing, and provider-resilience contract.
  • Create ADR-0032 describing the L1 IExceptionHandler, 8-step MediatR pipeline, Result.Fail-only validation behavior, DomainException-as-bug discipline, provider resilience via Polly v8, Sentry vs OpenTelemetry error-capture split, Serilog-as-primary logger, tenant-context span enrichment, error-tracking abstraction, and correlation propagation across HTTP/outbox/Hangfire/Hub.
  • Add architecture document 33-cross-cutting-concerns.md that narrates how errors, logs, traces, and metrics flow end-to-end, including diagrams and rationale for the two-track failure model and correlation semantics.
  • Update decisions index to register ADR-0032 and reference it as the source of truth for cross-cutting concerns.
docs/decisions/0032-exception-handling-logging-and-observability.md
docs/architecture/33-cross-cutting-concerns.md
docs/decisions/README.md
Align error-handling and observability standards with ADR-0032, including L1 exception handling, Result-based validation, domain exception rules, provider resilience, and Sentry/OTel boundaries.
  • Update error-handling standard to reference ADR-0032, switch the two-track diagram to use IExceptionHandler and Result.ToActionResult, document the L1 exception handler responsibilities, define the Sentry vs OpenTelemetry capture table, specify ValidationBehavior’s Result.Fail behavior, clarify DomainException usage and analyzer enforcement, define Result→IActionResult mapping, and describe provider resilience via IProviderResilience and Polly v8.
  • Update observability standard to reference ADR-0032 and document Serilog as the primary logger with OTLP sink (no OTel logger provider), correlation fields and propagation (including Hub /api/internal/* and outbox/Hangfire), TenantContextSpanProcessor + ITenantContextAccessor as the span enrichment mechanism, error span semantics, IErrorTrackingProvider deployment-mode mapping, and new guardrails against misusing logging, Sentry, and span tagging.
  • Extend the glossary with a Cross-Cutting Concerns section defining Result, Error, Pipeline Behavior, the L1 IExceptionHandler, correlation IDs, telemetry signals, IErrorTrackingProvider, IProviderResilience, ITenantContextAccessor, TenantContextSpanProcessor, ProviderException.IsClientError, and cache L1/L2 terminology.
docs/standards/09-error-handling.md
docs/standards/10-observability.md
docs/glossary.md
Update roadmap docs to make ADR-0032 a Phase 02a/02b contract and enumerate cross-cutting deliverables and architecture tests.
  • Amend Phase 02a roadmap to reference ADR-0032, add a Cross-cutting Concerns section listing concrete deliverables (LearnStackExceptionHandler, canonical MediatR pipeline, Result.ToActionResult, provider resilience decorator, Serilog+OTLP, TenantContextSpanProcessor, IErrorTrackingProvider, DomainException analyzer), and introduce new architecture tests to enforce these decisions.
  • Amend Phase 02b roadmap to reference ADR-0032 for outbox and Hangfire correlation propagation, specifying outbox row fields, tenant-context restoration, and tests ensuring correlation and tenant context are present in outbox rows, job payloads, and integration-event handler scopes.
docs/roadmap/phase-02a-kernel-tenancy.md
docs/roadmap/phase-02b-events-auth.md
Refine backend coding and infrastructure standards to lock in the canonical MediatR pipeline order and composition-root wiring, and to extend forbidden patterns for cross-cutting concerns.
  • Rewrite the pipeline behavior section in backend-coding standards to the 8-step canonical order with detailed responsibilities per behavior and an explicit statement that no ExceptionHandlingBehavior is allowed, backed by an architecture test checking DI registration order.
  • Extend infrastructure-stack standard with new rows for error tracking and OTLP exporter per DeploymentMode, and new forbidden rules around direct Sentry usage, direct provider SDK usage, and direct DeploymentMode reads from modules.
  • Clarify infrastructure standard 12’s dev stack documentation formatting and add ADR-0032/33 to the reference list.
docs/standards/02-backend-coding.md
docs/standards/20-infrastructure-stack.md
docs/standards/12-infrastructure.md
Enhance CLAUDE rules and skills so AI-assisted changes respect the new cross-cutting contract and wiring patterns.
  • Extend CLAUDE.md with explicit “do not” rules for DomainException, FluentValidation exceptions, Sentry SDK usage, ExceptionHandlingBehavior, OTel logger provider registration, Serilog.ILogger usage, provider SDK exception leakage, and manual tenant/correlation span tagging.
  • Update the add-mediatr-handler skill to reference the new pipeline order, Result.Fail vs exceptions, DomainException analyzer, ValidationBehavior behavior, and logging/audit interaction, plus new anti-patterns like logging-and-rethrowing and manual span tagging.
  • Add two new skills: wire-cross-cutting-foundation for wiring exception handling, MediatR pipeline, Serilog+OTel, TenantContextSpanProcessor, IErrorTrackingProvider, and IProviderResilience; and add-provider-adapter for creating new provider adapters with the standard port/adapter/resilience pattern and ProviderException mapping.
  • Update the skills index to include the new skills.
CLAUDE.md
.claude/skills/README.md
.claude/skills/add-mediatr-handler/SKILL.md
.claude/skills/wire-cross-cutting-foundation/SKILL.md
.claude/skills/add-provider-adapter/SKILL.md
Tighten documentation around Dapr and infra components to align phase ownership and architecture diagrams with current roadmap and ADRs.
  • Update the Dapr README to clarify which phases own IEventBus/ICacheService/ISecretProvider, that Dapr-backed implementations ship in Phase 02a with composition-root selection per DeploymentMode, switch the architecture sketch to Mermaid with a text fallback, and clarify that certain features (e.g., outbox) are 02b concerns.
  • Annotate the dev Coturn config with Phase 08c deferral notes, including external-ip behavior, LiveKit configuration, and credential strategy, to prevent premature productionization assumptions.
infra/dapr/README.md
infra/coturn/turnserver.conf

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitaiBot commented May 19, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@cemililik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 47 minutes and 54 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b93c2c1-d118-4c4a-b416-dc97427c0eb1

📥 Commits

Reviewing files that changed from the base of the PR and between 87af574 and 3b613d0.

📒 Files selected for processing (6)
  • .claude/skills/add-mediatr-handler/SKILL.md
  • .claude/skills/add-provider-adapter/SKILL.md
  • docs/architecture/33-cross-cutting-concerns.md
  • docs/decisions/0032-exception-handling-logging-and-observability.md
  • docs/roadmap/phase-02b-events-auth.md
  • infra/dapr/README.md
📝 Walkthrough

Walkthrough

This PR establishes ADR-0032 as the binding cross-cutting contract for LearnStack's exception handling, logging, observability, error tracking, and provider resilience. It documents the canonical architecture across multiple standards, adds comprehensive implementation guidance through two new skills, and integrates these patterns into Phase 02a and 02b roadmaps.

Changes

Cross-Cutting Exception Handling, Logging, and Observability Architecture

Layer / File(s)Summary
ADR 0032: Exception Handling, Logging, and Observability
docs/decisions/0032-exception-handling-logging-and-observability.md, docs/decisions/README.md
Binding ADR specifying L1 IExceptionHandler mapping to RFC 7807 Problem Details, canonical 8-step MediatR pipeline order, DomainException reserved for programmer errors, provider-adapter resilience via Polly v8, Serilog-first logging with OTLP export, IErrorTrackingProvider abstraction keyed by DeploymentMode, OTel enrichment via TenantContextSpanProcessor and AsyncLocal ITenantContextAccessor, Sentry vs OpenTelemetry error capture boundary, and contractual correlation propagation through outbox and Hangfire.
Architecture Definition and Concepts
docs/architecture/33-cross-cutting-concerns.md, docs/glossary.md
Architecture documentation defining two-track failure model (Exception vs Result), exception hierarchy, MediatR pipeline responsibilities, logging/tracing/metrics stacks, deployment-mode composition-root branching, correlation propagation via W3C traceparent, provider resilience pattern, and frontend Problem Details integration; glossary defines cross-cutting terminology (Result/Error, pipeline steps, exception handling, correlation, error tracking, provider resilience, tenant context, cache layers).
Backend Coding and Error Handling Standards
docs/standards/02-backend-coding.md, docs/standards/09-error-handling.md
MediatR pipeline refactored to explicit 8-step ADR-cited sequence with per-behavior control-flow and architecture test enforcement; error handling expanded with dedicated L1 Exception Handler specification, exception hierarchy including TenantContextMissingException, Sentry vs OpenTelemetry capture boundary table, API surface guidance (ValidationBehavior returns Result.Fail, DomainException vs Result.Fail distinction, ToActionResult() mapping), and provider resilience via IProviderResilience with adapter namespace enforcement.
Observability and Infrastructure Standards
docs/standards/10-observability.md, docs/standards/20-infrastructure-stack.md, docs/standards/12-infrastructure.md
Observability aligned with ADR-0032: Serilog-first with OTLP export, OTel traces/metrics, IErrorTrackingProvider deployment-mode selection, organization_id correlation, correlation propagation through background jobs/outbox/Hub endpoints, centralized TenantContextSpanProcessor enrichment, error span semantics distinguishing exceptions from Result.Fail, forbidden OTel LoggerProvider/Serilog.ILogger/direct Sentry references in modules; infrastructure standard adds deployment-mode matrix for error tracking and OTLP targets, forbidden Sentry.SentrySdk rule, ADR-0032 reference; code-fence language fixes for Docker Compose rendering.
Architecture Tests Catalogue
docs/standards/21-architecture-tests-catalogue.md, docs/standards/README.md
New architecture-test/analyzer catalogue as single source of truth for test/analyzer identifiers, assertions, sources, enforcement approach, and phases; includes workflow guidance for adding/renaming/retiring entries, initial cross-cutting error/logging/observability rules, placeholders for backfilling earlier ADRs, and reference links to originating ADRs/standards.
CLAUDE.md Engineering Rules
CLAUDE.md
Extends "Things to never do" with explicit rules: use Result.Fail instead of throwing DomainException for business rules, restrict ValidationException throwing, route error capture via IErrorTrackingProvider, rely on AuditLogBehavior/IExceptionHandler, avoid double OTel/Serilog export, use Microsoft.Extensions.Logging.ILogger, bound SDK exceptions to adapter namespaces, centralize span tagging for tenant/organization/user/correlation fields.
Wire Cross-Cutting Foundation Skill
.claude/skills/wire-cross-cutting-foundation/SKILL.md
Canonical 12-step composition-root wiring skill: ADR/boundaries adhesion, NuGet packages, Serilog as primary logger with enrichment/routing to OTel, AsyncLocal ITenantContextAccessor singleton, OpenTelemetry tracing/metrics with resource/instrumentation/OTLP/air-gapped swap, IErrorTrackingProvider by DeploymentMode (Sentry SDK import restriction), L1 IExceptionHandler/ProblemDetails with recording and conditional capture, canonical 8-step MediatR pipeline (forbidding separate ExceptionHandlingBehavior), IProviderResilience extension with config section selection, Result.ToActionResult() extension pattern, DomainException Roslyn analyzer, module service registration ordering. Includes validation checklist, common pitfalls, and references to ADRs/standards/skills.
Add Provider Adapter Skill
.claude/skills/add-provider-adapter/SKILL.md
Canonical pattern for external provider adapter integrations: when/when-not-to-use guidance; 8-step workflow (port interface in SharedKernel, ProviderException subclass with isClientError semantics, translation-only adapter implementation, composition-root IProviderResilience extension, appsettings.Resilience:: configuration shape, retry behavior by isClientError, integration tests for 4xx/5xx and circuit-breaker, module spec entry). Includes validation checklist, common pitfalls (retry in adapter, SDK exception leakage, misset isClientError, missing config, adapter reuse, bypassing port interface), and references to ADRs/standards.
Add MediatR Handler Skill Update
.claude/skills/add-mediatr-handler/SKILL.md
Updates documentation to clarify shared MediatR pipeline as explicit sequence (Validation → Logging → Audit → TenantContext → Authorization → Transaction → OutboxFlush → Handler); expands Common pitfalls with "unexpected failures" definition and audit-related guidance; adds new pitfalls discouraging handler-level error re-logging after L1 exception handler and per-call Activity.Current tenant tag setting.
Skills Catalog Index
.claude/skills/README.md
Inserts two new backend skill entries: wire-cross-cutting-foundation and add-provider-adapter into the numbered catalogue after wire-dapr-pubsub with proper numbering and table structure.
Phase 02a and 02b Roadmap Integration
docs/roadmap/phase-02a-kernel-tenancy.md, docs/roadmap/phase-02b-events-auth.md
Phase 02a adds ADR-0032 to codified decisions; introduces "Cross-cutting Concerns (Day 1)" section enumerating exception handling setup, 8-step MediatR pipeline, Result-to-ActionResult convention, domain-exception Roslyn analyzer, provider resilience decorator, Serilog + OTLP logging, OpenTelemetry instrumentation, ITenantContextAccessor-backed span processor, and IErrorTrackingProvider socket; extends architecture test checklist with cross-cutting coverage items; adds cross-cutting foundation components and wire-cross-cutting-foundation skill to deliverables. Phase 02b adds ADR-0032 reference; requires ITenantContext restoration and Activity creation with traceparent from outbox correlation_id for continuous tracing; extends architecture tests with outbox/Hangfire correlation assertions and handler tenant-context resolution checks.
Infrastructure Documentation
infra/dapr/README.md, infra/coturn/turnserver.conf
Dapr README refines building-block phase ownership, replaces ASCII topology with Mermaid graph and text fallback describing daprd/workstation connectivity and traffic routing, updates Dapr-aware types phase reference to 02a, adds architecture tests line. Coturn dev config adds deferred productionization comment block clarifying external-ip intentional omission, LiveKit wiring deferral, and static vs per-session TURN credentials timing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


🐰 A rabbit's ode to the cross-cutting flow,
Where exceptions and telemetry brightly glow,
Eight pipeline steps dance in ordered delight,
With Serilog and OTel shining so bright,
The foundation is wired, the patterns are clear,
LearnStack's observability brings joy and cheer!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately describes the main change: introducing ADR-0032 documenting the exception handling, logging, and observability architecture foundation.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phase-01-infra-identity-eventing

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 and usage tips.

@sourcery-aisourcery-aiBot 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.

Hey - I've left some high level feedback:

  • The exception hierarchy now recommends using System.Diagnostics.UnreachableException directly in Standards 09, but ADR-0032 / 33-cross-cutting still list UnreachableException generically in the LearnStack hierarchy; consider explicitly naming the BCL type and clarifying that it is not a LearnStackException subclass to avoid confusion and namespace collisions.
  • ADR-0032, the standards, and the skills docs all hard-code many analyzer and architecture test identifiers (e.g. MediatR_Pipeline_Order_Matches_Canonical_Sequence, LearnStackException-DomainExceptionThrow); consider adding a small central index/table of these test/analyzer names and linking to it from the docs so renames or relocations only need to be updated in one place.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments- The exception hierarchy now recommends using `System.Diagnostics.UnreachableException` directly in Standards 09, but ADR-0032 / 33-cross-cutting still list `UnreachableException` generically in the LearnStack hierarchy; consider explicitly naming the BCL type and clarifying that it is not a `LearnStackException` subclass to avoid confusion and namespace collisions.
- ADR-0032, the standards, and the skills docs all hard-code many analyzer and architecture test identifiers (e.g. `MediatR_Pipeline_Order_Matches_Canonical_Sequence`, `LearnStackException-DomainExceptionThrow`); consider adding a small central index/table of these test/analyzer names and linking to it from the docs so renames or relocations only need to be updated in one place.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@gemini-code-assistgemini-code-assistBot 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.

Code Review

This pull request establishes a comprehensive cross-cutting foundation for error handling, logging, and observability, primarily codified in the new ADR-0032. Key changes include the implementation of a two-track failure model, a canonical eight-step MediatR pipeline, and a standardized provider-resilience pattern using Polly v8. Review feedback identified opportunities to refine the L1 exception handler by excluding client cancellations from error telemetry, suggested providing a concrete implementation for server-side error detection in the adapter templates, and recommended explicit referencing of the BCL UnreachableException to maintain consistency across documentation.

Comment on lines +507 to +508
Activity.Current?.RecordException(ex);
Activity.Current?.SetStatus(ActivityStatusCode.Error, ex.GetType().Name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The implementation snippet for LearnStackExceptionHandler contradicts the error capture boundary defined in Sub-decision 7 and Standards 09. For OperationCanceledException, the span status should not be set to Error and the exception should not be recorded, as it represents an expected client disconnection rather than a system failure. Recording the exception typically forces the span status to Error in most OpenTelemetry exporters.

Suggested change
Activity.Current?.RecordException(ex);
Activity.Current?.SetStatus(ActivityStatusCode.Error, ex.GetType().Name);
if (ex is not OperationCanceledException)
{
Activity.Current?.RecordException(ex);
Activity.Current?.SetStatus(ActivityStatusCode.Error, ex.GetType().Name);
}

throw new LiveClassProviderException(
"provider.quota_exceeded", ex.Message, ex, isClientError: true);
}
catch (HttpRequestException ex) when (IsServerError(ex))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The adapter template uses an undefined IsServerError(ex) helper. Since this skill is intended for AI agents to follow, providing the implementation of this helper or using a direct check on the StatusCode property of HttpRequestException (available in .NET 5+) would ensure the generated code is correct and follows the ADR-0032 mapping rules (where null status codes like DNS failures are treated as infrastructure faults).

Suggested change
catch (HttpRequestException ex) when (IsServerError(ex))
catch (HttpRequestException ex) when (ex.StatusCode is null || (int)ex.StatusCode >= 500)

fault; Sentry).
- `TenantContextMissingException` — request reached the pipeline without a
resolved tenant.
- `UnreachableException` — case branch the type system can't prove

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

To maintain consistency with Standards 09, this reference should explicitly mention System.Diagnostics.UnreachableException to clarify that the BCL exception is preferred over a custom subclass for this specific use case.

Suggested change
-`UnreachableException` — case branch the type system can't prove
-System.Diagnostics.UnreachableException — case branch the type system can't prove

cemililikand others added 2 commits May 20, 2026 01:46
PR #2 picked up three medium-severity findings from gemini-code-assist
and one matching upper-level note from sourcery-ai (coderabbit rate-
limited; no review). All three are snippet corrections — narrow scope,
no contract change.
- G1: LearnStackExceptionHandler snippet (ADR-0032 § Implementation
Notes) called Activity.RecordException + SetStatus(Error)
unconditionally, contradicting Sub-decision 7's rule that
OperationCanceledException stays out of the error path. Snippet now
short-circuits OperationCanceled before the exception-recording
branch. Standards 09 and Architecture 33's "SetStatus(Cancelled)"
notation also corrected — ActivityStatusCode has only Unset / Ok /
Error, so the right value for a client disconnect is "leave Unset"
(no RecordException, no SetStatus call). Three files touched.
- G2: add-provider-adapter skill's LiveKitClient template used an
undefined IsServerError(ex) helper in a `catch (HttpRequestException)
when (...)` clause. .NET 5+ exposes HttpRequestException.StatusCode
as HttpStatusCode? — null means transport failure (DNS, refused,
timeout) which is an infra fault. Snippet now uses
`ex.StatusCode is null || (int)ex.StatusCode >= 500`, matching
ADR-0032 § Sub-decision 5's IsClientError mapping table.
- G3: 33-cross-cutting-concerns.md's exception-hierarchy bullet list
still mentioned `UnreachableException` generically. Standards 09
switched to the BCL `System.Diagnostics.UnreachableException` in the
earlier review round; Architecture 33 now matches with the same
qualified name and the explicit "not a LearnStackException subclass"
clarification sourcery requested.
Sourcery's second upper-level suggestion — a central index of
architecture-test / Roslyn-analyzer identifiers so renames only touch
one place — is acknowledged but out of scope for this PR. The catalog
will emerge naturally in Phase 02a when the tests are actually written.
Ref: PR #2 reviews from gemini-code-assist and sourcery-ai (2026-05-19).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…R-0032 unreachable note
Two sourcery upper-level findings on PR #2:
1. ADR-0032 and Architecture 33 listed `UnreachableException` generically
while Standards 09 had already switched to the BCL
`System.Diagnostics.UnreachableException`. Risk: future readers see
the ADR's generic name and add a custom `LearnStackException`
subclass, colliding with the BCL type. Resolved by adding an
explicit note under ADR-0032 § Sub-decision 4 clarifying that the
BCL type is the sanctioned one and is **not** a `LearnStackException`
subclass. (Architecture 33 already carried the qualified name from
the previous review round.)
2. Architecture-test and Roslyn-analyzer identifiers
(`MediatR_Pipeline_Order_Matches_Canonical_Sequence`,
`LearnStackException-DomainExceptionThrow`, …) were hard-coded across
5-8 documents each. Rename or relocation forced a multi-file edit
with no single source of truth. Resolved by creating
`docs/standards/21-architecture-tests-catalogue.md` as the canonical
registry: per-identifier section with assertion + source + type +
phase, and a documented "rename touches the catalogue first" rule.
Catalogue scope in this PR: the 12 architecture tests + 1 Roslyn
analyzer introduced by ADR-0032. Earlier-ADR tests (audit, Dapr,
tenancy, deployment-mode) are listed as "to be backfilled" — they
migrate into the catalogue as their source docs are touched, no
rewrite-for-rewrite churn.
Cross-link wiring:
- Standards 02 / 09 / 10 / Roadmap 02a / 02b / CLAUDE.md each gain a
one-paragraph pointer to the catalogue alongside their existing
identifier mentions. Eight cite sites in total.
- Standards index gains row 21.
- ADR-0032 References list gains the catalogue.
Naming convention codified in the catalogue: architecture tests use
`Subject_Constraint` (no ADR number baked in — the ADR cite belongs in
the test's `[Description]` attribute, not the type name); Roslyn analyzer
IDs use `LearnStackException-<Topic>`. The two namespaces are disjoint by
prefix.
Ref: PR #2 sourcery review (2026-05-19).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@coderabbitaicoderabbitaiBot 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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
infra/dapr/README.md (1)

119-120: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Conflicting phase ownership in this document needs to be resolved

Line 119 and Line 120 say the IEventBus / ICacheService / ISecretProvider implementations are Phase 02b, but Line 18–23 and Line 86 state they ship in Phase 02a. Please make these sections consistent so phase ownership is unambiguous.

Based on learnings "Foundation building blocks (Dapr IEventBus/ICacheService/ISecretProvider, APISIX gateway, audit infrastructure, organization scope, entitlement projection socket, host-to-tenant resolver, architecture tests) ship in Phase 02a".

🤖 Prompt for 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.
In `@infra/dapr/README.md` around lines 119 - 120, Resolve the conflicting phase
assignment for the Dapr interfaces by making all mentions of IEventBus,
ICacheService, and ISecretProvider consistently indicate Phase 02a (not 02b);
update the sentence at the current Phase 02b reference so it reads that these
implementations ship in Phase 02a and ensure any surrounding text referencing
phases (the earlier section that lists foundation building blocks and the line
that currently says Phase 02b) match this single source of truth for IEventBus,
ICacheService, and ISecretProvider.
🧹 Nitpick comments (1)
.claude/skills/add-mediatr-handler/SKILL.md (1)

253-255: ⚡ Quick win

Clarify Result.Fail mapping boundary (controller vs pipeline).

This wording implies the pipeline performs RFC7807 mapping, but Result<T>.ToActionResult() is an API/controller mapping step. Tightening this sentence avoids implementation drift.

Proposed wording tweak
- The pipeline maps `Result.Fail` to RFC 7807 Problem Details automatically via- `Result<T>.ToActionResult()`.+ The API/controller layer maps `Result.Fail` to RFC 7807 Problem Details via+ `Result<T>.ToActionResult()`.
🤖 Prompt for 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.
In @.claude/skills/add-mediatr-handler/SKILL.md around lines 253 - 255, The
sentence currently implies the pipeline maps Result.Fail to RFC7807, but the
mapping is actually performed at the controller/API layer via
Result<T>.ToActionResult(); update the wording in SKILL.md to state that
Result.Fail values are converted to RFC7807 Problem Details when controllers
call Result<T>.ToActionResult(), and reference ADR-0032 § Sub-decision 4 for
policy rather than claiming the pipeline performs the mapping; locate the
sentence referencing Result.Fail and Result<T>.ToActionResult() and rephrase to
clearly separate pipeline behavior from controller/API mapping.
🤖 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 @.claude/skills/add-provider-adapter/SKILL.md:
- Around line 30-40: The fenced code block in SKILL.md is missing a language
tag; update the opening fence from ``` to ```text (or another appropriate
language) so the block containing ResilientProviderAdapter<TPort>, LiveKitClient
and ProviderException is fenced as ```text ... ``` to satisfy MD040 and your
docs CI.
In `@docs/architecture/33-cross-cutting-concerns.md`:
- Around line 76-103: The two unlabeled fenced code blocks containing the
request/behavior flow (the block starting with "Request ▼ [1] ValidationBehavior
... [8] Handler") and the OTel notes block must be updated to include a language
marker (e.g., ```text or ```mermaid) to satisfy MD040; edit the fenced blocks
that contain those exact snippets and replace the opening ``` with ```text (or
convert to ```mermaid if you want rendering), and also apply the same fix to the
other unlabeled block referenced (the one around lines 206-219) so all
diagrammatic/code fences in this document have explicit language markers.
In `@docs/decisions/0032-exception-handling-logging-and-observability.md`:
- Around line 155-165: The unlabeled fenced code block that contains the
pipeline diagram starting with "Request → ValidationBehavior" must be marked
with an explicit language tag; update that fenced block to begin with ```text
(or ```mermaid if you prefer to render it) so the markdown linter (MD040) and
repository guidelines for diagrams are satisfied.
In `@docs/roadmap/phase-02b-events-auth.md`:
- Around line 45-46: Clarify that the outbox's correlation_id is not a free-form
UUID but must be stored (or converted) into a full W3C traceparent header value;
update the docs around Activity, traceparent and correlation_id to state whether
the outbox row contains the complete traceparent string
(version-trace-id-parent-id-trace-flags) or, if it only stores a correlation_id,
describe the exact deterministic mapping/serialization rule to construct a valid
traceparent (how to derive trace-id, parent-id, version and trace-flags from
correlation_id) so consumers can set Activity.Traceparent correctly and preserve
end-to-end trace continuity.
In `@infra/dapr/README.md`:
- Line 16: The roadmap link in infra/dapr/README.md currently points to
phase-02b-events-outbox-identity.md but the canonical file in this PR is
phase-02b-events-auth.md; update the link target in the README (the line
containing
"[phase-02b](../../docs/roadmap/phase-02b-events-outbox-identity.md)") to
reference ../../docs/roadmap/phase-02b-events-auth.md so the link points to the
renamed file.
---
Outside diff comments:
In `@infra/dapr/README.md`:
- Around line 119-120: Resolve the conflicting phase assignment for the Dapr
interfaces by making all mentions of IEventBus, ICacheService, and
ISecretProvider consistently indicate Phase 02a (not 02b); update the sentence
at the current Phase 02b reference so it reads that these implementations ship
in Phase 02a and ensure any surrounding text referencing phases (the earlier
section that lists foundation building blocks and the line that currently says
Phase 02b) match this single source of truth for IEventBus, ICacheService, and
ISecretProvider.
---
Nitpick comments:
In @.claude/skills/add-mediatr-handler/SKILL.md:
- Around line 253-255: The sentence currently implies the pipeline maps
Result.Fail to RFC7807, but the mapping is actually performed at the
controller/API layer via Result<T>.ToActionResult(); update the wording in
SKILL.md to state that Result.Fail values are converted to RFC7807 Problem
Details when controllers call Result<T>.ToActionResult(), and reference ADR-0032
§ Sub-decision 4 for policy rather than claiming the pipeline performs the
mapping; locate the sentence referencing Result.Fail and
Result<T>.ToActionResult() and rephrase to clearly separate pipeline behavior
from controller/API mapping.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 96a3fcb5-6b65-4365-aa12-8e939c9ac56f

📥 Commits

Reviewing files that changed from the base of the PR and between ce88bc3 and 87af574.

📒 Files selected for processing (20)
  • .claude/skills/README.md
  • .claude/skills/add-mediatr-handler/SKILL.md
  • .claude/skills/add-provider-adapter/SKILL.md
  • .claude/skills/wire-cross-cutting-foundation/SKILL.md
  • CLAUDE.md
  • docs/architecture/33-cross-cutting-concerns.md
  • docs/decisions/0032-exception-handling-logging-and-observability.md
  • docs/decisions/README.md
  • docs/glossary.md
  • docs/roadmap/phase-02a-kernel-tenancy.md
  • docs/roadmap/phase-02b-events-auth.md
  • docs/standards/02-backend-coding.md
  • docs/standards/09-error-handling.md
  • docs/standards/10-observability.md
  • docs/standards/12-infrastructure.md
  • docs/standards/20-infrastructure-stack.md
  • docs/standards/21-architecture-tests-catalogue.md
  • docs/standards/README.md
  • infra/coturn/turnserver.conf
  • infra/dapr/README.md

Comment thread.claude/skills/add-provider-adapter/SKILL.md Outdated
Comment threaddocs/architecture/33-cross-cutting-concerns.md Outdated
Comment threaddocs/decisions/0032-exception-handling-logging-and-observability.md Outdated
Comment threaddocs/roadmap/phase-02b-events-auth.md Outdated
Comment threadinfra/dapr/README.md Outdated
…s + dapr README
Walked each review finding against current code; all seven were still
valid, all minimal scope, all applied.
Inline comments
---------------
- add-provider-adapter L30-40: ASCII flow diagram fence had no language
tag. Added ```text.
- 33-cross-cutting-concerns L76 + L206: two ASCII-flow fences without
language tags. Added ```text to both.
- ADR-0032 L155: pipeline diagram fence without language tag. Added ```text.
- phase-02b L41-46: clarified that outbox `correlation_id` is the **full
W3C traceparent string** (`00-<32-hex>-<16-hex>-<2-hex>`), not a bare
UUID. Consumer rehydrates via `ActivityContext.TryParse(...)` +
`_activitySource.StartActivity(name, kind, parentCtx)`. Same
clarification mirrored into ADR-0032 § Sub-decision 12 so the binding
contract and the roadmap deliverable agree on the wire format.
- infra/dapr/README.md L16: link target was
`phase-02b-events-outbox-identity.md` (stale name from an earlier
rename). Updated to `phase-02b-events-auth.md`.
Outside-diff comments
---------------------
- infra/dapr/README.md "What does NOT live here" listed the Dapr
interface implementations under Phase 02b, contradicting § Phase
ownership above which (correctly) places them in Phase 02a. Rewrote
the bullet so the document speaks with one voice: interfaces +
adapters ship in 02a; only the outbox dispatch path (the sanctioned
caller of `IEventBus.PublishAsync`) is 02b.
Nitpick
-------
- add-mediatr-handler Common-pitfalls: previous wording implied "the
pipeline maps Result.Fail to RFC 7807 automatically via
Result<T>.ToActionResult()". Mapping actually happens at the
controller/API boundary when the endpoint explicitly calls
`.ToActionResult()` (Step 7 above) — the pipeline just propagates
Result unchanged. Rephrased to separate pipeline behaviour from
controller mapping.
Ref: PR #2 review batch (2026-05-19/20).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cemililik
cemililik merged commit 5d3c35f into mainMay 19, 2026
2 checks passed
Sign up for freeto 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

@cemililik