acru. Loyalty Pilot · operator console & consumer surface — working prototype
Maison Clay · Shopify · mrc_7d2a USDC · Base Sepolia Simulated data — no real funds How this maps to the RFP ↓
1
Ingest
orders/paid · HMAC
2
Idempotency
key per order ID
3
Cohort gate
treatment only
4
Reward rule
rate × subtotal
5
Issue USDC
treasury → wallet
6
Ledger
append-only entry
Simulate the store D1

Each button delivers a signed Shopify orders/paid webhook. Watch it move through the pipeline above.

Reward rule D3
reward = 5.0% × order subtotal
5.0%

Rule rate_x_subtotal · configurable at runtime, per merchant — never a hard-coded constant. The next order picks up the new rate.

Treasury · hot wallet D7
$2,500.00 USDC
alert below $500 0xA7c4…91Ee
⚠ Balance under alert threshold — operator notified. Fund the treasury to keep issuing.
Fund treasuryAcru-held keys · KMS (simulated)
Issuance activepause holds orders; nothing is lost
Pilot cohort D2
800

Treatment

800

Control

ID list imported 2026-07-21 · every gating decision is logged. Gating lives in an isolated module so it lifts out cleanly after the pilot.

Event stream D1·D6
Ledger — double-entry, append-only D6

Every earn, spend and withdrawal is an immutable entry. Balances are derived from these rows — never stored as a mutable field. The wallet on the right is reading this same ledger.

SeqTimeEntryDebitCreditUSDC
0 entries phone user derived balance: $0.00 keyed to merchant customer IDs — joins cleanly to Shopify exports

Consumer surface · mobile web — D4 · email login, no app, no crypto knowledge needed

9:41 ▮▮▮ ᯤ ▐▌
Maison Clayrewards by acru.

No app and no passwords — we email you a six-digit code. You'll stay signed in on this device for the pilot.

Maison Clayrewards by acru.

Enter your code

We sent a six-digit code to you@example.com.

Signing in creates your wallet automatically — nothing to set up, no seed phrase, ever.

Maison Clayrewards by acru.
Your balance
$0.00
Held as USDC on Base — yours to keep

Activity

a

No rewards yet

Shop at Maison Clay and 5% of your order lands here automatically, usually within a minute of checkout.

You stay signed in during the pilot. A code is only ever asked for when money leaves your wallet.

Spend at Maison Clay

Turn your balance into a store credit code and apply it at checkout. Maison Clay honors it instantly; Acru settles with the store.

Available: $0.00

Your credit code

Store credit · Maison Clay
ACRU-0000

$0.00 · single use · valid 30 days

Paste it in the discount field at checkout, or show it in store. Your balance updated the moment the code was created.

Withdraw to bank

Move your balance to your bank account. Acru processes withdrawals within one business day.

Identity verified with our payments provider — required once, before your first withdrawal.

Available: $0.00

Confirm it's you

For your security, withdrawals need a fresh code. We sent one to you@example.com.

This is the only time we re-ask for a code — day-to-day, you stay signed in.

🏦

Withdrawal requested

$0.00 is on its way to your bank. Acru processes withdrawals within one business day — we'll email you when it lands.

Your balance updated immediately, and the request is queued for Acru's operations team.

+$0.00 from your order at Maison Clay

Built to the RFP, line by line

Everything above is the pilot workflow from §2, on the prescribed stack from §3, honoring the architecture in §4.

§4 · Non-negotiable 1

Merchant abstraction

Every entity in this prototype — orders, customers, rules, ledger rows, credit codes — is keyed to mrc_7d2a (Maison Clay).

The build implements a pluggable connector interface; Shopify is connector #1. A second merchant is a config entry, not a rewrite.

§4 · Non-negotiable 2

Ledgered balances

The ledger above is double-entry and append-only. The phone's balance is derived by folding its entries — try it: spend or withdraw, and watch the same rows drive both surfaces.

No mutable balance field exists anywhere in the design.

§4 · Non-negotiable 3

Rule-driven issuance

The reward is the rule rate_x_subtotal — change the rate in the console and the very next webhook computes against it.

Rules are per-merchant configuration, versioned in the build so every issuance records which rule produced it.

D1In prototype
Purchase-event ingestion

Signed orders/paid webhooks, HMAC verified, raw events persisted, idempotent on order ID — use "Redeliver last webhook."

D2In prototype
Cohort gating

Treatment issues, control logs a decision and stops. Isolated module, removable after the pilot.

D3In prototype
Issuance engine

Rule × subtotal, USDC transfer, wallet auto-created on first earn, idempotency key per order, ledger entry per event.

D4In prototype
Consumer web surface

Email OTP login, persistent session, balance, spend, withdraw with OTP re-auth — the phone on the right.

D5In prototype
Redemption + settlement

Store credit codes the merchant honors and Acru reconciles; assisted withdraw-to-bank per §6 — automation quoted separately.

D6In prototype
Event log + export

Every earn, spend, withdrawal and login timestamped; CSV export keyed to merchant customer IDs for control-group analysis.

D7In prototype
Admin / monitoring

Treasury balance + alert threshold, live issuance feed, and a pause switch that holds orders without losing them.

D8Build scope
Deployment + handover

Digital Ocean via IaC, Acru-owned accounts and keys, operator runbook, 30-day support window, team walkthrough.

Compliance flags we would raise in writing (§9): the withdraw-to-bank path may implicate money-transmission rules depending on custody structure; reward issuance in a stable-value asset may need reward-structure disclosure review; KYC/sanctions screening thresholds on withdrawal sit with Acru's counsel. The build documents each decision point before launch — we surface the questions, counsel makes the call.