SRS: UC_9.13 — Flow 36: Dots Retainer Ledger Sync
| Field | Value |
|---|---|
| UC_ID | UC_9.13 |
| Version | v1.0 |
| Last Updated | 2026-10-27 |
| BA PiC | linh.nguyen34 |
| Category | BACKGROUND MECHANISMS & CRON JOBS |
| Module | Flow 36 (UC_4.15.2) |
| Function | Dots Retainer Ledger Sync |
| Document References | Zapier Integration V7.pdf (§Flow 36; §7.3 Flow 36 Retainer Trigger — Option B) · RFQ_ Stack Trading Prop Tech V7.pdf (§Record Immutable Ledger; §3.6.1; §Audit Requirements) · StackTrading_Backend_Technical_Proposal_v1.6.docx (§Option B — Dots ✓) |
1. UC Index
| UC_ID | Function | Description |
|---|---|---|
| UC_9.13 | Flow 36 — Dots Retainer Ledger Sync | When Dots processes the monthly retainer for an active International Contractor (Level 6+), the event enters through the Middleware Hub hardened ingress (Option B), is emitted to Zapier as RETAINER_PROCESSED, and Zapier calls POST /api/ledger/record to mint a Payroll Executed event ($[Total_Amount] Retainer Paid ([billing_country])) on Polygon PoS. |
UC_9.13 — Flow 36: Dots Retainer Ledger Sync
| Field | Value |
|---|---|
| Use Case | Dots Retainer Ledger Sync |
| Description | Publishes proof of international contractor retainer payment to the Immutable Ledger. One processed Dots retainer = one CorporateMetricVerified event with the Dots Transaction ID as verificationHash. |
| Actor | System (Dots → Middleware Hub → Zapier → Middleware Hub → Polygon PoS) |
| Zapier Flow | Flow 36 |
| Trigger Source | Middleware Hub event RETAINER_PROCESSED (source: Dots, Monthly Retainer Processed) |
| 3rd Party | Dots · Zapier · Alchemy RPC · Polygon PoS |
| Middleware Endpoints | POST /webhooks/retainer/dots (ingress) · POST /zapier/events/retainer_processed (emit) · POST /api/ledger/record |
| Related UCs | UC_9.11 · UC_9.2 (Path B hiatus suspends / resumes retainer) · UC_4.15.2 |
2. Trigger
| Stage | Component | Action |
|---|---|---|
| Ingress | POST /webhooks/retainer/dots | Validate Dots signature / allowlist; enforce idempotency via provider_event_id; write to event_log before emitting. |
| Emit | POST /zapier/events/retainer_processed | Emit normalized RETAINER_PROCESSED event (source: Dots) to Zapier. |
| Zap | Flow 36 | Triggered by the Middleware Hub event. |
(Source: Zapier Integration V7.pdf §7.3 Option B · StackTrading_Backend_Technical_Proposal_v1.6.docx §Option B provider list — Dots ✓)
3. Pre-conditions
| ID | Pre-condition |
|---|---|
| P1 | Dots webhook configured to POST /webhooks/retainer/dots. |
| P2 | Payload contains Dots Transaction ID, Total_Amount, and payee reference resolvable to trader_id. |
| P3 | Trader is an active International Contractor at Level 6+. |
| P4 | billing_country available on the Users table. |
| P5 | Ledger contract and owner wallet available (see UC_9.11 P4). |
4. Post-conditions
| # | Post-condition |
|---|---|
| 1 | Dots event persisted in event_log (durable, replayable). |
| 2 | One CorporateMetricVerified event with metricCategory = "Payroll Executed". |
| 3 | tx_hash stored in PostgreSQL; execution logged to BPS_Audit_Log. |
| 4 | Zap terminates. |
5. Basic Flow
Step 1 — Ingress (Middleware). Receive Dots webhook at POST /webhooks/retainer/dots → validate signature → dedup on provider_event_id (duplicate → Alt-1) → write event_log.
Step 2 — Emit (Middleware). POST /zapier/events/retainer_processed with normalized payload.
(Source: Zapier Integration V7.pdf §7.3 Option B)
Step 3 — Filter (Zapier). Continue only if payload corresponds to an active Stack Trading International Contractor (Level 6+). Otherwise stop (Alt-2).
(Source: Zapier Integration V7.pdf §Flow 36)
Step 4 — Call POST /api/ledger/record
| Field | Value |
|---|---|
trader_id | Global trader UUID |
metric_category | "Payroll Executed" (fixed) |
metric_value | "$[Total_Amount] Retainer Paid ([billing_country])" — e.g. "$2,500.00 Retainer Paid (UK)" |
date | Today (ISO 8601 UTC) |
receipt_hash | Dots Transaction ID |
(Source: Zapier Integration V7.pdf §Flow 36)
Step 5 — Middleware mints on Polygon — same as UC_9.11 Step 5.
Step 6 — Terminate Zap.
6. Alternative Flows
Alt-1 — Duplicate Dots delivery: ingress dedup on provider_event_id returns HTTP 200 to Dots; nothing emitted to Zapier.
Alt-2 — Not an active L6+ International Contractor: Zap stops at filter; no ledger call.
7. Exceptional Flows
Exc-1 — Dots signature invalid: ingress rejects (HTTP 401); no event_log row; audit row REJECTED.
Exc-2 — Zapier JWT invalid / Polygon RPC failure: same as UC_9.11 Exc-1 / Exc-2. Because the event is in event_log, Ops can replay it.
8. Business Rules
BR_9.13.1: Scope — Active International Contractor, Level 6+
Below Level 6, traders are on the on-demand bonus model (no retainer). US W-2 payroll is Flow 34.
(Source: Zapier Integration V7.pdf §Flow 36)
BR_9.13.2: Fixed Ledger Mapping
metric_category = "Payroll Executed"; metric_value = "$[Total_Amount] Retainer Paid ([billing_country])"; receipt_hash = Dots Transaction ID.
(Source: Zapier Integration V7.pdf §Flow 36)
BR_9.13.3: Hardened Ingress (Option B) Is Mandatory for Dots
Dots webhooks enter via Middleware Hub (signature validation, provider_event_id dedup, event_log write before emit). Dots must not call Zapier directly.
(Source: Zapier Integration V7.pdf §7.3 · StackTrading_Backend_Technical_Proposal_v1.6.docx §Option B)
BR_9.13.4: One Retainer = One Ledger Event
Dedup at ingress (provider_event_id) and at POST /api/ledger/record (receipt_hash). No duplicate ledger entries.
(Source: Zapier Integration V7.pdf §7.3 — "Ensure downstream actions are idempotent (no duplicate ledger entries / payouts / accounting entries)")
BR_9.13.5: Audit Retention
Same as BR_9.11.7.
9. Acceptance Criteria
| AC_ID | Flow | Given | Then | Type |
|---|---|---|---|---|
| AC-9.13-01 | Happy path | Dots retainer $2,500.00 processed for active L6+ contractor, billing_country = UK | event_log row; Zapier event emitted; one on-chain event "$2,500.00 Retainer Paid (UK)", verificationHash = Dots Transaction ID | Integration |
| AC-9.13-02 | Duplicate | Dots retries same event | Ingress returns HTTP 200; no second emit; one on-chain event | Integration |
| AC-9.13-03 | Below L6 / W-2 | Payload for L5 or W-2 trader | Zap stops; no ledger call | Integration |
| AC-9.13-04 | Bad Dots signature | Invalid signature | HTTP 401; no event_log row | Security |
| AC-9.13-05 | Replay | RPC failed for event X | Ops replays X from event_log; exactly one on-chain event results | Integration |
10. API Reference
POST /api/ledger/record — schema as UC_9.11 §10.
{
"trader_id": "94a2b1c8-3f4e-4b21-a123-890abcdef123",
"metric_category": "Payroll Executed",
"metric_value": "$2,500.00 Retainer Paid (UK)",
"date": "2026-03-31T18:00:00Z",
"receipt_hash": "dots_txn_441029381"
}11. Open Questions
| ID | Priority | Question | Assumption |
|---|---|---|---|
| Q1 | M | billing_country display format — ISO alpha-2 (GB) or label (UK)? V7 example shows UK. | ISO alpha-2 from Users table; GB displayed as-is. Confirm. |
| Q2 | M | Prorated one-time retainer (Level 7+ raise mid-month) — does it fire the same Dots event and get logged? | Yes, logged as a separate event. |
| Q3 | L | Does Flow 36 update any invoice record (e.g. mark paid)? Not in V7. | No — ledger only. |
12. Changelog
| Date | Version | Change | Previous | After | Source |
|---|---|---|---|---|---|
| 2026-10-27 | v1.0 | Initial document creation | — | Full spec: Option B ingress, L6+ contractor filter, ledger mint, BR_9.13.1–5, AC-9.13-01–05 | Zapier Integration V7.pdf §Flow 36, §7.3; Backend Proposal v1.6 §Option B |