feat(stripe-core): dunite-stripe-core shared Stripe primitives (DEV-514) #27

Merged
longjacksonle merged 2 commits from feat/DEV-514-dunite-stripe-core into main 2026-08-03 18:07:12 +02:00

What

First shared-crate extraction under the DEV-495 epic (DEV-514). Adds dunite-stripe-core: a framework-agnostic crate holding the small, security-relevant Stripe primitives that a8n-tools, bunyip, and mokosh had each reimplemented.

Contents

  • verify_webhook_signature - constant-time Stripe-Signature verification (t=/v1=, timestamp tolerance, multi-v1 rotation). Uses hmac's verify_slice for a constant-time compare.
  • parse_event_envelope - pulls the event id + type off a verified body and returns the raw JSON so the consumer decodes data.object in whatever shape it needs (typed async-stripe for a8n/bunyip, raw fields for mokosh).
  • to_minor_units / from_minor_units - money major<->minor conversion (rust_decimal, two-decimal currencies).

Why framework-agnostic

a8n-api and bunyip-api are actix; bunyip-web and mokosh are axum. The crate has no HTTP framework, no database, and no async-stripe dependency, so all three consumers call it from their own handlers. Larger SDK-coupled Stripe code (product/price/subscription API wrappers, response DTOs) is deliberately out of scope, tracked as DEV-515.

Notable

Standardizes on the constant-time signature comparison, which fixes a8n-tools' non-constant-time == on a billing path (the bug bunyip filed as BUNYIP-107) once a8n adopts the crate.

Tests

15 unit tests (signature accept/reject/stale/future/rotation/malformed, event parse, money round-trip/rounding) + 1 doctest. cargo test -p dunite-stripe-core, cargo clippy -p dunite-stripe-core --all-targets -- -D warnings, and cargo fmt --check all clean. The crate joins the virtual workspace, so its tests run in dunite's check.yml.

Consumers

Wired first into mokosh-server (separate PR). bunyip and a8n-tools adoption follow under DEV-514.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QLd9c7niucrqx68v4AxVss

## What First shared-crate extraction under the DEV-495 epic (DEV-514). Adds `dunite-stripe-core`: a framework-agnostic crate holding the small, security-relevant Stripe primitives that a8n-tools, bunyip, and mokosh had each reimplemented. ## Contents - `verify_webhook_signature` - constant-time `Stripe-Signature` verification (`t=/v1=`, timestamp tolerance, multi-`v1` rotation). Uses `hmac`'s `verify_slice` for a constant-time compare. - `parse_event_envelope` - pulls the event `id` + `type` off a verified body and returns the raw JSON so the consumer decodes `data.object` in whatever shape it needs (typed `async-stripe` for a8n/bunyip, raw fields for mokosh). - `to_minor_units` / `from_minor_units` - money major<->minor conversion (`rust_decimal`, two-decimal currencies). ## Why framework-agnostic a8n-api and bunyip-api are actix; bunyip-web and mokosh are axum. The crate has no HTTP framework, no database, and no `async-stripe` dependency, so all three consumers call it from their own handlers. Larger SDK-coupled Stripe code (product/price/subscription API wrappers, response DTOs) is deliberately out of scope, tracked as DEV-515. ## Notable Standardizes on the constant-time signature comparison, which fixes a8n-tools' non-constant-time `==` on a billing path (the bug bunyip filed as BUNYIP-107) once a8n adopts the crate. ## Tests 15 unit tests (signature accept/reject/stale/future/rotation/malformed, event parse, money round-trip/rounding) + 1 doctest. `cargo test -p dunite-stripe-core`, `cargo clippy -p dunite-stripe-core --all-targets -- -D warnings`, and `cargo fmt --check` all clean. The crate joins the virtual workspace, so its tests run in dunite's `check.yml`. ## Consumers Wired first into mokosh-server (separate PR). bunyip and a8n-tools adoption follow under DEV-514. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QLd9c7niucrqx68v4AxVss
First shared-crate extraction under the DEV-495 epic. A framework-agnostic crate holding the small, security-relevant Stripe building blocks that a8n-tools, bunyip, and mokosh each reimplemented: constant-time Stripe-Signature verification (t=/v1=, timestamp tolerance, multi-v1 rotation), webhook event-envelope parsing (id + type + raw JSON for the consumer to decode data.object), and money major<->minor conversion. No HTTP framework, no database, no async-stripe SDK - pure functions each stack calls from its own actix or axum handler, so it is adoptable by all three consumers regardless of framework. Standardizes on the constant-time comparison, fixing a8n-tools' non-constant-time signature check on a billing path. Larger SDK-coupled Stripe code (product/price/subscription API wrappers, response DTOs) stays out, tracked as DEV-515.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLd9c7niucrqx68v4AxVss
chore: lock dunite-stripe-core deps (DEV-514)
All checks were successful
Check / fmt + clippy + test (pull_request) Successful in 41s
create-release / create-release (pull_request) Has been skipped
0734f2adb4
Cargo.lock entries for the new crate and its hmac / rust_decimal deps, so a `--locked` build resolves.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLd9c7niucrqx68v4AxVss
longjacksonle deleted branch feat/DEV-514-dunite-stripe-core 2026-08-03 18:07:12 +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!27
No description provided.