refactor(stripe): consume dunite-stripe StripeService (DEV-515 pt 2) #450

Merged
longjacksonle merged 3 commits from feat/DEV-515-consume-stripe-service into main 2026-08-04 01:59:29 +02:00

Consumer side of DEV-515 part 2. dunite PR #30 moved the async-stripe StripeService into the shared dunite-stripe crate; this drops bunyip's copy and re-exports the shared one, so a8n-tools and bunyip drive one Stripe client instead of two that drift.

What changed

  • crates/bunyip-domain/src/services/stripe.rs loses ~1400 lines (the whole async-stripe service body plus its tests, which now live in the crate) and becomes a re-export of StripeService / StripeConfig / StripeServiceError plus the bits that are genuinely bunyip's. crate::services::stripe::* import paths are unchanged for every caller.
  • StripeConfig::from_env / from_db_model become the free functions stripe_config_from_env / stripe_config_from_db_model, since StripeConfig is now a foreign type. They stay bunyip-side because they use the {NAME}_FILE compose-secret convention, the bunyip app-tag default, the CORS_ORIGIN-derived checkout URLs, and bunyip's EncryptionKeySet for secret decryption.
  • 33 StripeService call sites across admin, admin_stripe, billing, membership and webhook gain .map_err(stripe_err).
  • dunite-stripe pinned at rev 41dbbeb (an ancestor of dunite main since #30 merged).

Why a neutral error and not AppError

The crate returns its own StripeServiceError and stripe_err maps it to AppError at each call site. Returning dunite_core::AppError from the crate was tried on a branch and reverted: a path dep on dunite-core forces every git consumer to unify its own dunite-core to the rev dunite-stripe pins, which cascades through dunite-download/oci/oidc and would drag unmerged dunite-oidc changes into bunyip-oidc. A blanket From<StripeServiceError> for AppError is impossible either way, both types being foreign to bunyip (orphan rule), so the .map_err at the call sites is the cost of the decoupling.

stripe_err preserves the variant, so no endpoint changes status code or body.

Verification

  • cargo clippy --workspace --all-targets -- -D warnings clean
  • cargo fmt --all --check clean
  • cargo test --workspace --lib: 294 + 108 + 15 + 9 passed, 0 failed (includes the moved config tests and a new stripe_err_maps_variants)

🤖 Generated with Claude Code

https://claude.ai/code/session_01CGnY8JKXCgH2jiUSqH6g4x

Consumer side of DEV-515 part 2. dunite PR #30 moved the async-stripe `StripeService` into the shared `dunite-stripe` crate; this drops bunyip's copy and re-exports the shared one, so a8n-tools and bunyip drive one Stripe client instead of two that drift. ## What changed - `crates/bunyip-domain/src/services/stripe.rs` loses ~1400 lines (the whole async-stripe service body plus its tests, which now live in the crate) and becomes a re-export of `StripeService` / `StripeConfig` / `StripeServiceError` plus the bits that are genuinely bunyip's. `crate::services::stripe::*` import paths are unchanged for every caller. - `StripeConfig::from_env` / `from_db_model` become the free functions `stripe_config_from_env` / `stripe_config_from_db_model`, since `StripeConfig` is now a foreign type. They stay bunyip-side because they use the `{NAME}_FILE` compose-secret convention, the `bunyip` app-tag default, the `CORS_ORIGIN`-derived checkout URLs, and bunyip's `EncryptionKeySet` for secret decryption. - 33 `StripeService` call sites across admin, admin_stripe, billing, membership and webhook gain `.map_err(stripe_err)`. - `dunite-stripe` pinned at rev `41dbbeb` (an ancestor of dunite main since #30 merged). ## Why a neutral error and not `AppError` The crate returns its own `StripeServiceError` and `stripe_err` maps it to `AppError` at each call site. Returning `dunite_core::AppError` from the crate was tried on a branch and reverted: a path dep on dunite-core forces every git consumer to unify its own dunite-core to the rev dunite-stripe pins, which cascades through dunite-download/oci/oidc and would drag unmerged dunite-oidc changes into bunyip-oidc. A blanket `From<StripeServiceError> for AppError` is impossible either way, both types being foreign to bunyip (orphan rule), so the `.map_err` at the call sites is the cost of the decoupling. `stripe_err` preserves the variant, so no endpoint changes status code or body. ## Verification - `cargo clippy --workspace --all-targets -- -D warnings` clean - `cargo fmt --all --check` clean - `cargo test --workspace --lib`: 294 + 108 + 15 + 9 passed, 0 failed (includes the moved config tests and a new `stripe_err_maps_variants`) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01CGnY8JKXCgH2jiUSqH6g4x
Deletes the 1400-line async-stripe service body from bunyip-domain and re-exports `StripeService` / `StripeConfig` from the shared `dunite-stripe` crate, so a8n-tools and bunyip drive the same Stripe client instead of two drifting copies. `crate::services::stripe::*` import paths are unchanged for every caller.

What stays bunyip-side is the part that is genuinely bunyip's: `stripe_config_from_env` (uses the `{NAME}_FILE` compose-secret convention, the `bunyip` app-tag default, and the `CORS_ORIGIN`-derived checkout URLs) and `stripe_config_from_db_model` (decrypts with bunyip's `EncryptionKeySet`). Both were inherent `StripeConfig::from_*` constructors before; they become free functions because `StripeConfig` is now a foreign type.

The crate returns a neutral `StripeServiceError` rather than `dunite_core::AppError`, and `stripe_err` maps it at the call sites. Returning `AppError` was tried and reverted: it forces the consumer's `dunite-core` rev to unify with the one `dunite-stripe` pins, which cascades through dunite-download/oci/oidc and drags unmerged dunite-oidc changes into bunyip-oidc. A blanket `From<StripeServiceError> for AppError` is impossible either way (orphan rule, both types foreign).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGnY8JKXCgH2jiUSqH6g4x
Mechanical follow-up to the service swap: the 33 `StripeService` call sites across admin, admin_stripe, billing, membership and webhook now `.map_err(stripe_err)` because the shared crate returns its own neutral error type, and the two config constructors are called as free functions (`stripe_config_from_env`, `stripe_config_from_db_model`) now that `StripeConfig` is foreign. No behaviour change: `stripe_err` preserves the variant, so every endpoint keeps its existing status code and body.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGnY8JKXCgH2jiUSqH6g4x
Merge remote-tracking branch 'origin/main' into feat/DEV-515-consume-stripe-service
All checks were successful
E2E PR gate / Install + reachability (no deployment secrets) (pull_request) Successful in 23s
Check / fmt + clippy + build + tests (pull_request) Successful in 13m48s
Create release / Create release from merged PR (pull_request) Has been skipped
6e54f98899
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-04 01:46:32 +02:00
longjacksonle deleted branch feat/DEV-515-consume-stripe-service 2026-08-04 01:59:29 +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/bunyip!450
No description provided.