BE-4067 whole-mando error unwalling

BE-4067 FINISHED the mando error-stack “unwalling” that BE-4047 began: it removed ALL remaining production raw error_stack::Report<C> from mando-lib and adopted the full BE-4000 devex idiom (#[mando_error] + #[cause(...)] + bare ?) everywhere. The walls that BE-3657 error_stack Adoption phase 3 documented as structurally frozen are now gone.

For Agents

Branch feature/BE-4067 @ 0dff4f2d, stacked on feature/BE-4047 (!599). 9 commits, one per subsystem. GOAL ACHIEVED: zero production raw-Report in mando-lib. Final whole-branch review verdict: READY-TO-MERGE, no findings. Gates: lib 376/0, clippy --all-features clean, no cross-crate ripple. Spec + plan (untracked): docs/superpowers/specs/2026-08-04-be4067-whole-mando-unwalling-design.md + docs/superpowers/plans/2026-08-04-be4067-whole-mando-unwalling.md.

What “unwalled” means (goal achieved)

Zero production raw-Report in mando-lib, verified three ways:

  • git grep into_mando_result -- mando-lib/src = 0 (the tower-edge lift verb has no remaining production call site).
  • The ONLY production into_report().into_inner() left is the intentional body of the shared wrap_http_call helper.
  • Zero raw-Report-returning production fns remain.

This closes the “walled service towers” finding from BE-3657 error_stack Adoption phase 3: the seven flat-typed towers that made cross-crate Report flow “structurally impossible” are all restructured; Reports now flow to the step boundary through the native MandoReport idiom.

The 9 commits (one per subsystem)

#CommitSubsystem
1b6086f79wrap_http_call helper (the new shared pattern, see below)
252205518fingrid
323da1335data_platform
49346d7c9metis
5cc638039ebs
692c6da5fopl report_polars born-lift
7fa1b1fa2ems service tower
878c567e6atp (delete VolueAtpAuthenticationProviderError)
90dff4f2dfingrid into_mando_result cleanup (branch tip)

The new pattern: wrap_http_call

The one genuinely new artifact worth recording. In mando-lib/src/adapter/http_cause.rs:

#[track_caller]
fn wrap_http_call<E, F>(source: HttpCallError, make: F) -> MandoReport<E>

Why a helper and NOT a #[cause] macro route

wrap_http_call is a shared helper, not a #[cause] message-only route. It replaced the triplicated HttpCallError -> ApiError wrap at metis / fingrid / ems. A #[cause(...)] route is message-only, but ApiError is multi-field (it carries a source) AND re-attaches an opaque HttpContext - a #[cause] route would DROP both. The helper preserves them.

Must keep #[track_caller]

wrap_http_call MUST retain #[track_caller] so the caller’s file/line survives into emission. Dropping it silently degrades every wrapped HTTP error’s location back to the helper body (the same #[track_caller]-loss trap that bit the earlier map_err(fn-pointer) migrations).

The recipe: BE-4047’s a/b/c + step (d)

BE-4067 extends the BE-4047 conversion recipe with a fourth step:

  • (d) message-only foreign-error maps become #[cause(ForeignErr)] + bare ?.

KEEP manual construction (do NOT collapse to #[cause]) for:

  • Multi-field variants: NonSuccessStatus, InvalidUrl, CannotParseJson (they carry structured fields).
  • Context-prefixed / multi-source maps: ebs SambaError, data_platform SdkError (they prepend context or fold several sources).

The dividing line is the same as wrap_http_call’s rationale: a #[cause] route only carries a message, so anything with fields or attached context stays hand-constructed.

ems SERVICE tower gotcha

Associated Error type is E, not Result

The step-service tower’s type Error = Report<VolueEmsError> becomes type Error = MandoReport<VolueEmsError> - NOT MandoResult<..>. The FlowStepService::Error associated type IS the error type E, never the result alias. Getting this wrong is the easy mistake here.

Location note: the ems service tower lives under service/volue/ems/* (the SERVICE layer), not under adapter/. The adapter-layer ems changes are separate.

atp: deleted VolueAtpAuthenticationProviderError

Commit 78c567e6 DELETES the VolueAtpAuthenticationProviderError enum outright as part of unwalling atp. The knock-on: new()’s error signature changed, but there was no cross-crate ripple - the change is absorbed by an anyhow ? at mando-bess/src/lib.rs:198 (the init path is anyhow-typed, so the tightened error type just flows through).

Emission preserved (BE-4014 harness)

Emission fidelity is pinned per-subsystem via Datadog goldens using the BE-4014 Datadog Error-Rendering Test Harness. Goldens are location-trimmed (volatile file/line omitted so the subset matcher ignores them). 11 dd_emission tests pass - the unwalling is a refactor, not a behavior change, and the goldens prove it.

Gates + review

  • Final whole-branch review: READY-TO-MERGE, no findings.
  • lib gate: 376 passed / 0 failed.
  • cargo clippy --all-features: clean.
  • No cross-crate ripple (atp’s new() error change absorbed by the anyhow ? at mando-bess/src/lib.rs:198).

North-star context

BE-4067 is the mando-ERRORS axis of the larger conformance goal (conformant traces AND errors across all BESS services). Still-open children:

  • mando trace / instrumentation conformance (the trace axis, not touched here).
  • error + trace conformance in bess-optimization / bess-forecast-day-ahead / the dashboards (downstream services).
  • Phase 4 #[error_meta] (per-variant metadata: event type, resolution step, business message, description).
  • The not-yet-landed error.trace field + .step_context() helper (the two redesign pieces that never landed on develop).
graph LR
    A["BE-3657<br/>error_stack adoption"] --> B["BE-4000<br/>#[mando_error] derive"]
    B --> C["BE-4047<br/>unwalling begun"]
    C --> D["<b>BE-4067</b><br/>unwalling FINISHED<br/>zero raw-Report in mando-lib"]
    D --> E["still open:<br/>trace conformance,<br/>downstream services,<br/>phase 4 #[error_meta]"]
    style D fill:#264653,stroke:#2a9d8f,color:#fff
    style E fill:#3d2020,stroke:#a55,color:#fff
  • BE-4067 error DX clarity - the grammar-clarity + mando-bess-lib adoption follow-on, stacked directly on this branch’s tip: renames #[cause] #[reframe]/#[chain]/#[transparent], makes MandoReport opaque, and adopts the 25 mando-bess-lib service enums into the error system (a DD telemetry change on the financial flows)
  • BE-4047 - the unwalling phase this FINISHES; BE-4067 is stacked directly on it (!599)
  • BE-4000 derive transplant - the #[mando_error] / #[cause(...)] / bare-? devex idiom BE-4067 adopts everywhere
  • BE-3657 error_stack Adoption - master error-stack trail; its phase-3 “walled towers” finding is what BE-4067 dismantles
  • BE-4014 Datadog Error-Rendering Test Harness - the DD golden harness pinning per-subsystem emission fidelity (11 dd_emission tests)
  • Agent Context