SRS: UC_9.11 — Flow 34: Rippling Payroll Ledger Sync
| Field | Value |
|---|---|
| UC_ID | UC_9.11 |
| Version | v1.1 |
| Last Updated | 2026-11-04 |
| BA PiC | linh.nguyen34 |
| Category | BACKGROUND MECHANISMS & CRON JOBS |
| Module | Flow 34 (UC_4.15.2) |
| Function | Rippling Payroll Ledger Sync |
| Document References | Zapier Integration V7.pdf (§Flow 34; §7.2 Flow 34 Payroll Trigger — Option A/B) · RFQ_ Stack Trading Prop Tech V7.pdf (§Record Immutable Ledger POST /api/ledger/record; §3.6.1 Smart Contract Architecture; §Audit Requirements CFTC 1.31) · StackTrading_Backend_Technical_Proposal_v1.6.docx (§Option B provider list) · QnA_STAGE5_PAYOUT_WITHDRAWAL.md (A-33) |
1. UC Index
| UC_ID | Function | Description |
|---|---|---|
| UC_9.11 | Flow 34 — Rippling Payroll Ledger Sync | When Rippling clears a bi-weekly/monthly payroll run for an active W-2 trader, Zapier calls POST /api/ledger/record to mint a W2 Payroll Executed event on the Polygon PoS StackTradingLedger contract. Middleware stores the returned tx_hash in PostgreSQL. Duplicate Rippling deliveries are de-duplicated by provider_event_id / receipt_hash. |
UC_9.11 — Flow 34: Rippling Payroll Ledger Sync
| Field | Value |
|---|---|
| Use Case | Rippling Payroll Ledger Sync |
| Description | Publishes proof of W-2 payroll (base salary + benefits) to the Immutable Ledger. Each cleared regular scheduled Rippling payroll run (bi-weekly/monthly) for an active W-2 trader produces exactly one CorporateMetricVerified event on Polygon PoS, with the Rippling Transaction ID as verificationHash. Off-cycle runs are ignored. |
| Actor | System (Rippling → Zapier → Middleware Hub → Polygon PoS) |
| Zapier Flow | Flow 34 |
| Trigger Source | Rippling webhook — Payroll Run Cleared (PAYROLL_CLEARED) |
| 3rd Party | Rippling · Zapier · Alchemy RPC · Polygon PoS |
| Middleware Endpoint | POST /api/ledger/record |
| Related UCs | UC_7.4 Immutable Ledger (Payout) · UC_4.15.2 Career & HR Widget · Flow 5 (performance bonus), Flow 9 (severance), Flow 17 (Pod Leader vesting) — each logs its own off-cycle W-2 payout to the ledger, see BR_9.11.6 |
2. Trigger
Event: Rippling fires a webhook when a regular scheduled bi-weekly or monthly payroll run is cleared (funds disbursed).
Off-cycle runs (Flow 5 performance bonus, Flow 9 severance, Flow 17 Pod Leader vesting — all via Rippling Off-Cycle Payroll API) are not processed by Flow 34, even if Rippling fires the same webhook. See Alt-3.
| Source | Event | Delivery path |
|---|---|---|
| Rippling | Payroll Run Cleared (PAYROLL_CLEARED) | Option A — direct to Zapier (Rippling is not in the Option B hardened-ingress provider list) |
(Source: Zapier Integration V7.pdf §Flow 34; §7.2 Option A/B · StackTrading_Backend_Technical_Proposal_v1.6.docx §Option B provider list — Rippling marked "—")
⚠️ Option B (
POST /webhooks/payroll/rippling→POST /zapier/events/payroll_cleared) is described in Zapier Integration V7.pdf §7.2 but is not in the adopted Option B scope (8 providers: NMI, Triple-A, Skrill, Nomupay, EBANX, Dusupay, Veriff, Dots). See Q1.
3. Pre-conditions
| ID | Pre-condition |
|---|---|
| P1 | Rippling webhook subscription to Payroll Run Cleared is configured to the Zapier Flow 34 catch hook. |
| P2 | Payload contains a Rippling Transaction ID (used as receipt_hash) and the payroll amount (Total_Amount). |
| P3 | The Rippling worker maps to a Stack Trading user (trader_id) whose Employment_Type = 'W-2' and status is active. |
| P4 | StackTradingLedger contract is deployed on Polygon PoS Mainnet; the server-side owner wallet private key is available to Middleware (secured environment). |
4. Post-conditions
| # | Post-condition |
|---|---|
| 1 | One CorporateMetricVerified event emitted on Polygon PoS with metricCategory = "W2 Payroll Executed". |
| 2 | Polygon tx_hash written to PostgreSQL (ledger record) against trader_id + receipt_hash. |
| 3 | receipt_hash / provider_event_id marked processed — any redelivery is a no-op. |
| 4 | Execution logged to BPS_Audit_Log. |
| 5 | Event becomes visible on GET /public/ledger (Live Payout Ledger ticker) after the cache refresh. |
| 6 | Zap terminates. |
5. Basic Flow
Step 1 — Receive webhook (Zapier)
Zapier catch hook receives the Rippling Payroll Run Cleared payload.
Step 2 — Filter: active W-2 trader, regular payroll run only (Zapier)
- Resolve the Rippling worker to
trader_id. - Continue only if the trader is an active Stack Trading W-2 trader (
Employment_Type = 'W-2', account active). - Continue only if the payroll run is a regular scheduled run (not off-cycle). Off-cycle → stop (see Alt-3).
- Otherwise → stop (see Alt-2).
- ⚠️ The Rippling payload field that distinguishes a regular run from an off-cycle run is not in the sources — Dev to confirm against the Rippling API.
(Source: Zapier Integration V7.pdf §Flow 34 — "Ensure payload corresponds to an active Stack Trading W2 Trader Only"; QnA_BACKGROUND_MECHANISMS_CRON.md [BG-016] — client sheet 2026-11-04)
Step 3 — Dedup check
Before calling the ledger, check provider_event_id (Rippling event / transaction ID) against the dedup store. If already processed → Alt-1.
(Source: Zapier Integration V7.pdf §7.2 Option A — "Store provider_event_id in DB to dedup (required for payroll/ledger events)")
Step 4 — Call Middleware POST /api/ledger/record
| Field | Value |
|---|---|
trader_id | Global trader UUID |
metric_category | "W2 Payroll Executed" (fixed) |
metric_value | "$[Total_Amount] Base + Benefits Paid" — amount formatted to 2 decimal places with thousands separator, e.g. "$4,500.00 Base + Benefits Paid" |
date | Today (ISO 8601 UTC) |
receipt_hash | Rippling Transaction ID |
(Source: Zapier Integration V7.pdf §Flow 34)
Step 5 — Middleware mints on Polygon
- Validate the Zapier JWT signature. Reject if invalid (Exc-1).
- Initialize the server-side Ethers.js wallet using the secured environment private key.
- Execute
contract.recordMetric(_traderId, _metricCategory, _metricValue, _timestamp, _verificationHash)via Alchemy RPC, mapping:trader_id → _traderId,metric_category → _metricCategory,metric_value → _metricValue,date → _timestamp,receipt_hash → _verificationHash. - Await block confirmation.
- Write
tx_hashto PostgreSQL; log toBPS_Audit_Log. - Return
HTTP 200 { "status": "success", "tx_hash": "0x..." }.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Record Immutable Ledger; §3.6.1 Smart Contract Architecture)
Step 6 — Terminate Zap.
6. Alternative Flows
Alt-1 — Duplicate delivery
provider_event_id/receipt_hashalready processed.- Middleware does not call
recordMetric()again; returnsHTTP 200with the previously storedtx_hash. - No second ledger event; no second ticker row.
Alt-2 — Payload is not an active W-2 trader
- Filter fails (contractor, terminated, unknown worker, non-trader employee).
- Zap stops at Step 2. No ledger call. No error.
Alt-3 — Rippling reports an off-cycle payroll run
- Zap stops at Step 2. No ledger call. No error.
- Off-cycle W-2 payouts are already logged by their own flow via
POST /api/ledger/record: Flow 5 (Performance Bonus, Path C), Flow 9 (Severance, Path C), Flow 17 (Pod Leader Vesting, US W-2 path). Logging them again in Flow 34 would create duplicate on-chain entries.
(Source: QnA_BACKGROUND_MECHANISMS_CRON.md [BG-016] — client sheet 2026-11-04; Zapier Integration V7.pdf §Flow 5 Path C, §Flow 9 Path C; RFQ_ Stack Trading Prop Tech V7.pdf §Process Pod Vesting — Immutable Ledger Logging)
7. Exceptional Flows
Exc-1 — Invalid / expired Zapier JWT
- Middleware returns
HTTP 401; no contract call; log toBPS_Audit_Logwithexecution_status = REJECTED.
Exc-2 — Polygon RPC / transaction failure
recordMetric()fails or confirmation is not received.- Middleware returns non-2xx; nothing written as processed (so the retry can mint).
- Zapier retry applies (see Q3). On final failure → Slack alert to Ops (channel per slack_channel_usage.md, see Q3).
Exc-3 — trader_id cannot be resolved from the Rippling worker
- Treated as Alt-2 (stop) and logged to
BPS_Audit_LogasUNMAPPED_RIPPLING_WORKERfor manual review. (BA assumption — see Q4)
8. Business Rules
BR_9.11.1: Scope — Active W-2 Traders Only
Flow 34 logs payroll only for active Stack Trading W-2 traders. International contractors are handled by Flow 36 (UC_9.13).
(Source: Zapier Integration V7.pdf §Flow 34)
BR_9.11.2: Fixed Ledger Mapping
metric_category is always "W2 Payroll Executed". metric_value format is "$[Total_Amount] Base + Benefits Paid", amount formatted to 2 decimal places (e.g. "$2,500.00 Base + Benefits Paid"). receipt_hash is always the Rippling Transaction ID.
(Source: Zapier Integration V7.pdf §Flow 34; QnA_BACKGROUND_MECHANISMS_CRON.md [BG-016])
BR_9.11.3: One Payroll Run = One Ledger Event (Idempotency)
provider_event_id must be stored and checked before minting. Rippling retries must never produce a second on-chain event. Duplicates return HTTP 200 with the original tx_hash.
(Source: Zapier Integration V7.pdf §7.2 Option A)
BR_9.11.4: Ledger Write Is Owner-Only, Event-Only
The contract stores no state; data is written only as CorporateMetricVerified event logs. Only the owner wallet may call recordMetric().
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §3.6.1)
BR_9.11.5: tx_hash Persisted Before Success Response
Middleware returns success to Zapier only after block confirmation and after tx_hash is written to PostgreSQL.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Record Immutable Ledger — "Await confirmation and write the Polygon transaction hash to PostgreSQL")
BR_9.11.6: Flow 34 Logs Regular Payroll Only — Off-Cycle Payouts Are Logged by Their Own Flow
Flow 34 logs only regular scheduled W-2 payroll (base salary, benefits). Off-cycle W-2 payouts are logged by the flow that triggers them, via POST /api/ledger/record: Flow 5 (Performance Bonus), Flow 9 (Severance), Flow 17 (Pod Leader Vesting). Flow 34 filters off-cycle runs out so each payment produces exactly one ledger entry.
(Source: QnA_BACKGROUND_MECHANISMS_CRON.md [BG-016] — client sheet 2026-11-04, supersedes the QnA_STAGE5_PAYOUT_WITHDRAWAL.md A-33 assumption that Flow 34 logs Path C off-cycle payouts; Zapier Integration V7.pdf §Flow 5, §Flow 9; RFQ_ Stack Trading Prop Tech V7.pdf §Process Pod Vesting)
BR_9.11.7: Audit Retention
Every execution is written to BPS_Audit_Log. Retention: 5 years + 1 month (CFTC 1.31 / NFA); objects older than 25 months move to cold storage.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Audit Requirements)
9. Acceptance Criteria
| AC_ID | Flow | Given | Then | Type |
|---|---|---|---|---|
| AC-9.11-01 | Happy path | Payroll Run Cleared for active W-2 trader, $4,500.00, new transaction ID | One CorporateMetricVerified event with metricCategory = "W2 Payroll Executed", metricValue = "$4,500.00 Base + Benefits Paid", verificationHash = Rippling Transaction ID; tx_hash stored; HTTP 200 | Integration |
| AC-9.11-02 | Duplicate | Same Rippling event delivered twice | Second call returns HTTP 200 with original tx_hash; only one on-chain event | Integration |
| AC-9.11-03 | Filter — contractor | Payload for a non-W-2 worker | Zap stops at filter; no ledger call | Integration |
| AC-9.11-04 | Filter — inactive | Payload for terminated W-2 trader | Zap stops; no ledger call | Integration |
| AC-9.11-05 | Bad JWT | Request with invalid signature | HTTP 401; no contract call; audit row REJECTED | Security |
| AC-9.11-06 | RPC failure | Alchemy returns error | Non-2xx returned; event not marked processed; retry mints exactly once | Integration |
| AC-9.11-07 | Public ledger | AC-9.11-01 completed | Event appears in GET /public/ledger recent_events after cache refresh | Integration |
| AC-9.11-08 | Filter — off-cycle | Rippling off-cycle run (e.g. severance) cleared for an active W-2 trader | Zap stops at filter; no ledger call; no on-chain event from Flow 34 | Integration |
| AC-9.11-09 | Amount format | Regular payroll run cleared, $2,500 | metricValue = "$2,500.00 Base + Benefits Paid" (2 decimal places) | Integration |
10. API Reference
POST /api/ledger/record
| Field | Value |
|---|---|
| Caller | Zapier (Flow 34) |
| Auth | Zapier JWT signature |
Request:
{
"trader_id": "94a2b1c8-3f4e-4b21-a123-890abcdef123",
"metric_category": "W2 Payroll Executed",
"metric_value": "$4,500.00 Base + Benefits Paid",
"date": "2026-03-15T18:00:00Z",
"receipt_hash": "rip_pay_8830192a7c41f"
}Response (HTTP 200):
{ "status": "success", "tx_hash": "0x..." }| Field | Type | Required | Description |
|---|---|---|---|
trader_id | STRING | Yes | Global trader UUID |
metric_category | STRING | Yes | "W2 Payroll Executed" |
metric_value | STRING | Yes | "$[Total_Amount] Base + Benefits Paid" |
date | STRING | Yes | ISO 8601 UTC |
receipt_hash | STRING | Yes | Rippling Transaction ID |
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Record Immutable Ledger)
11. Open Questions
| ID | Priority | Question | Assumption |
|---|---|---|---|
| Q1 | H | Rippling is not in the Option B provider list. Is Flow 34 delivered via Option A (Rippling → Zapier direct) or should Rippling be added to Option B (POST /webhooks/payroll/rippling)? | Option A; dedup done in Middleware at POST /api/ledger/record. |
| Q2 | M | Does a Rippling off-cycle run (severance, client said Flow 34 covers severance — A-33) also fire Payroll Run Cleared? If yes, should metric_value still read "Base + Benefits Paid"? | ✅ Answered 2026-11-04 — Flow 34 ignores off-cycle runs; see Alt-3, BR_9.11.6 ([BG-016]). |
| Q3 | M | Zapier retry count / backoff and Slack channel on final failure are not specified in V7. | Zapier default auto-replay; alert to Ops channel. |
| Q4 | L | Should an unmapped Rippling worker raise an Ops alert or only an audit row? | Audit row only. |
| Q5 | L | Total_Amount = gross or net pay? Currency always USD? | Gross, USD. |
12. Changelog
| Date | Version | Change | Previous | After | Source |
|---|---|---|---|---|---|
| 2026-11-04 | v1.1 | §1 Description, Related UCs; §2 Trigger; §5 Step 2 (off-cycle filter), Step 4 metric_value format; §6 Alt-3 (new); §8 BR_9.11.2, BR_9.11.6 (rewritten); §9 AC-9.11-08/09 (new); §11 Q2 | Flow 34 assumed to also log off-cycle runs incl. severance (A-33); BR_9.11.6 = Flow 34 vs Flow 5 only | Flow 34 = regular scheduled payroll only; off-cycle W-2 payouts logged by Flow 5 / Flow 9 / Flow 17; metric_value 2 decimal places | Client sheet 2026-11-04 [BG-016]; Zapier Integration V7.pdf §Flow 5, §Flow 9; RFQ V7 §Process Pod Vesting |
| 2026-10-27 | v1.0 | Initial document creation | — | Full spec: trigger, W-2 filter, dedup, ledger mint, BR_9.11.1–7, AC-9.11-01–07 | Zapier Integration V7.pdf §Flow 34, §7.2; RFQ_ Stack Trading Prop Tech V7.pdf §Record Immutable Ledger, §3.6.1; QnA A-33 |