feat(observability): error-log ring + trusted-proxy client-IP in dunite-core #39

Merged
nrupard merged 1 commit from feat/DEV-529-error-log-client-ip into main 2026-08-06 16:48:39 +02:00
Owner

What

Adds the request-observability edge to dunite-core (DEV-529, under BUNYIP-340), extracted from bunyip-api:

  • error_log module - an in-memory bounded ERROR-log ring (ErrorLogBuffer) + a tracing_subscriber::Layer (ErrorLogLayer) that captures ERROR events with their structured fields (category / route / client split out, the rest retained). Already generic; only the doc was de-branded.
  • middleware::client_ip - trusted-proxy client-IP resolution: resolve_client_ip(peer, xff, real_ip, trusted_proxies) (pure) + client_ip(&HttpRequest, trusted_proxies) (actix wrapper). Honours X-Forwarded-For / X-Real-IP only when the socket peer is inside the configured trusted-proxy CIDR set, so an untrusted client cannot spoof its address. Joins the existing middleware (request_id, security_headers, csrf).

Deps

Adds tracing-subscriber = "0.3" to the workspace and dunite-core (the Layer / Registry the ring plugs into), and ipnetwork to dunite-core (CIDR matching; already a workspace dep).

Validation

cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test -p dunite-core green in the pinned rust-builder image. Tests: ERROR-captured-not-warning, category filter, ring rotation, field retention (log); trusted-proxy XFF / real-ip, untrusted-peer-ignores-headers, empty-proxies, unparseable-forwarded, and the actix request reader (client-IP).

Consumer follow-up (bunyip, after merge)

  • error_log.rs -> re-export shim over dunite_core::error_log; the admin log view and the ErrorLogLayer wiring in main.rs consume the crate types.
  • extract_client_ip in bunyip-domain auth.rs keeps its thin wrapper (it reads bunyip's trusted-proxy config) but delegates to dunite_core::middleware::client_ip; resolve_client_ip is removed from bunyip. The ~30 crate::middleware::extract_client_ip call sites are unchanged.

Bumps the dunite-core graph rev (not dunite-user-core), so it does not cross the MembershipTier rename.

Topology note

error_log lands in dunite-core per the DEV-529 spec (a foundational observability primitive). It adds tracing-subscriber to the foundation; if you'd rather keep it a leaf crate, it's easy to move pre-consumption.

#DEV-529

## What Adds the request-observability edge to `dunite-core` (DEV-529, under BUNYIP-340), extracted from bunyip-api: - **`error_log`** module - an in-memory bounded ERROR-log ring (`ErrorLogBuffer`) + a `tracing_subscriber::Layer` (`ErrorLogLayer`) that captures ERROR events with their structured fields (`category` / `route` / `client` split out, the rest retained). Already generic; only the doc was de-branded. - **`middleware::client_ip`** - trusted-proxy client-IP resolution: `resolve_client_ip(peer, xff, real_ip, trusted_proxies)` (pure) + `client_ip(&HttpRequest, trusted_proxies)` (actix wrapper). Honours `X-Forwarded-For` / `X-Real-IP` only when the socket peer is inside the configured trusted-proxy CIDR set, so an untrusted client cannot spoof its address. Joins the existing middleware (request_id, security_headers, csrf). ## Deps Adds `tracing-subscriber = "0.3"` to the workspace and dunite-core (the `Layer` / `Registry` the ring plugs into), and `ipnetwork` to dunite-core (CIDR matching; already a workspace dep). ## Validation `cargo fmt --all --check`, `cargo clippy --workspace --all-targets -- -D warnings`, `cargo test -p dunite-core` green in the pinned rust-builder image. Tests: ERROR-captured-not-warning, category filter, ring rotation, field retention (log); trusted-proxy XFF / real-ip, untrusted-peer-ignores-headers, empty-proxies, unparseable-forwarded, and the actix request reader (client-IP). ## Consumer follow-up (bunyip, after merge) - `error_log.rs` -> re-export shim over `dunite_core::error_log`; the admin log view and the `ErrorLogLayer` wiring in `main.rs` consume the crate types. - `extract_client_ip` in bunyip-domain `auth.rs` keeps its thin wrapper (it reads bunyip's trusted-proxy config) but delegates to `dunite_core::middleware::client_ip`; `resolve_client_ip` is removed from bunyip. The ~30 `crate::middleware::extract_client_ip` call sites are unchanged. Bumps the dunite-core graph rev (not `dunite-user-core`), so it does not cross the `MembershipTier` rename. ## Topology note error_log lands in dunite-core per the DEV-529 spec (a foundational observability primitive). It adds `tracing-subscriber` to the foundation; if you'd rather keep it a leaf crate, it's easy to move pre-consumption. #DEV-529
feat(observability): add error-log ring + trusted-proxy client-IP to dunite-core
All checks were successful
Check / fmt + clippy + test (pull_request) Successful in 25s
create-release / create-release (pull_request) Has been skipped
89d9fa631c
Extracts bunyip-api's request-observability edge into dunite-core (DEV-529).

error_log: an in-memory bounded ERROR-log ring (ErrorLogBuffer) plus a tracing_subscriber::Layer (ErrorLogLayer) that captures ERROR events with their structured fields (category/route/client split out, the rest retained). Already generic; only the doc was de-branded.

middleware::client_ip: trusted-proxy client-IP resolution. resolve_client_ip(peer, xff, real_ip, trusted_proxies) is the pure core; client_ip(&HttpRequest, trusted_proxies) is the actix wrapper. X-Forwarded-For / X-Real-IP are honoured only when the socket peer is inside the trusted-proxy CIDR set, so an untrusted client cannot spoof its address. Joins the existing request_id / security_headers / csrf middleware.

Adds tracing-subscriber to the workspace and dunite-core (the Layer/Registry the ring plugs into) and ipnetwork to dunite-core (CIDR matching, already a workspace dep). lib.rs, middleware/mod.rs and CLAUDE.md updated.

#DEV-529
nrupard deleted branch feat/DEV-529-error-log-client-ip 2026-08-06 16:48:40 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/dunite!39
No description provided.