@crvouga/mockingbird-service-firstpromoter 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # Changelog — @crvouga/mockingbird-service-firstpromoter
2
2
 
3
+ ## 2.3.0 (2026-10-05)
4
+
5
+ ### Features
6
+
7
+ - compose mock admin APIs ([952bd1f](https://github.com/crvouga/mockingbird/commit/952bd1f679bd442c9a5348a0d9c4d40ad0ac165c))
8
+ - add Fargate task acceptance mock ([f65fc3f](https://github.com/crvouga/mockingbird/commit/f65fc3f293b2fdb41fd45dd1693a5420c6a5109a))
9
+ - keep resource views live ([82c80e1](https://github.com/crvouga/mockingbird/commit/82c80e110b4aa551a17d0ee451c5d08167755267))
10
+ - add LocalStack free tier mocks ([84b7d0c](https://github.com/crvouga/mockingbird/commit/84b7d0ccf4acc7257bb3c3b466a38e30d5b4ab33))
11
+ - implement github reference semantics ([10143e8](https://github.com/crvouga/mockingbird/commit/10143e8364905d77ccfa188d8b6573b1f1003c56))
12
+ - implement docker attach upgrade handshake ([39ad1a3](https://github.com/crvouga/mockingbird/commit/39ad1a39b47aeb423b11bc96230d59f1f5985fa0))
13
+ - preserve accepted docker mutations across response loss ([c2b2d7d](https://github.com/crvouga/mockingbird/commit/c2b2d7dafffe653b3ae9667ec5019d342a68e802))
14
+
15
+ ### Fixes and improvements
16
+
17
+ - validate flag groups and stabilize coverage ([9609704](https://github.com/crvouga/mockingbird/commit/96097045a4bdb9e2e66011addbb771fc003c4120))
18
+ - reconcile combined PR integration ([124d5be](https://github.com/crvouga/mockingbird/commit/124d5bed7576535ff481ce6da7d2369957799665))
19
+ - preserve inferred form headers ([02bdd28](https://github.com/crvouga/mockingbird/commit/02bdd2806a9a934607ecd7ffd0cfbe4f6ba80c91))
20
+
21
+ ### Dependencies
22
+
23
+ - `@crvouga/mockingbird-service-sqlite`
24
+
25
+ ## 2.2.0 (2026-10-04)
26
+
27
+ ### Features
28
+
29
+ - add scripted local API mock ([4a76a11](https://github.com/crvouga/mockingbird/commit/4a76a114e2efad45934e0a93cf29576fd418e15c))
30
+ - track sales exactly once ([085c87b](https://github.com/crvouga/mockingbird/commit/085c87b5bfe49cc749b17e97b315a321c01c9579))
31
+ - reconcile commission batches ([b95e99a](https://github.com/crvouga/mockingbird/commit/b95e99a32fce9bc83a97b12a16534ed773235ee0))
32
+ - list and retrieve referrals ([3f5d848](https://github.com/crvouga/mockingbird/commit/3f5d848a322dc7554e8a563e7591f0b0ad8c498d))
33
+
34
+ ### Fixes and improvements
35
+
36
+ - support embedded route parameters ([127cad9](https://github.com/crvouga/mockingbird/commit/127cad997ef106950c1b866070eea191ba54403f))
37
+ - preserve namespace URLs after main sync ([62a15ce](https://github.com/crvouga/mockingbird/commit/62a15ce9bd453069bde69e3a30c91efc01f8871b))
38
+
3
39
  ## 2.1.0 (2026-10-04)
4
40
 
5
41
  ### Features
@@ -12,10 +48,6 @@
12
48
  - fill the embedded viewport ([c1a35a4](https://github.com/crvouga/mockingbird/commit/c1a35a4789389ee9cd06c286d09bd47c4d06c71e))
13
49
  - make dialog cleanup immediate ([0c1a3c5](https://github.com/crvouga/mockingbird/commit/0c1a3c5b12584d50c19dcae595b951b8e5417b9c))
14
50
 
15
- ### Dependencies
16
-
17
- - `@crvouga/mockingbird-service-sqlite`
18
-
19
51
  ## 2.0.0 (2026-10-04)
20
52
 
21
53
  ### ⚠️ Breaking changes
package/README.md CHANGED
@@ -68,6 +68,13 @@ const { tid } = (await (await admin("/clicks", { ref_token: "nate91" })).json())
68
68
  | `POST /v2/company/promoters/archive` | `{ids: [..]}` → a completed batch `{id, status, total, selected_total, processed_count, failed_count, action_label, progress, processing_errors, …}`. |
69
69
  | `POST /v2/promoters/iframe_login?promoter_id=` | `{access_token, expires_in}`, or 404. |
70
70
  | `POST /v2/track/signup` | `{email, tid? \| promoter_id? \| ref_id?, uid?, skip_email_notification?}` → the referral. An unknown `tid`, promoter or ref token is 404; none of them is 400; an email already tracked is 422. With `autoConvert` (default on) the referral becomes a customer at once and `lead_becomes_referral` is posted. |
71
+ | `GET /v2/company/referrals` | A bare array of stored referrals and live promoter/campaign metadata. `q` searches email/uid; `ids[]`, `filters[type]=lead\|customer`, `filters[state]`, `filters[promoter_id]`, and inclusive `filters[created_at\|customer_since][from\|to]` filter before paging. `page` starts at 1; `per_page` defaults to 20 (max 100). Exhausted pages and unmatched searches return `[]`. |
72
+ | `GET /v2/company/referrals/{id}` | The same referral projection as listing. A numeric ID or `find_by=email\|uid` selects it; missing records are 404. |
73
+
74
+ The [official referral reference](https://docs.firstpromoter.com/api-reference-v2/api-admin/referrals/get-referrals)
75
+ specifies the bare array. Paging parameters and limits follow the official
76
+ [n8n client](https://github.com/firstpromoter/n8n-app/blob/0842d761a3c024e7cf3030e5a108447375f03807/nodes/FirstPromoter/GeneralFunctions.ts)
77
+ and [input definitions](https://github.com/firstpromoter/n8n-app/blob/0842d761a3c024e7cf3030e5a108447375f03807/nodes/FirstPromoter/FirstPromoter.node.ts).
71
78
 
72
79
  Every call needs `Authorization: Bearer <key>` and an `Account-ID` header (else 401).
73
80
 
@@ -89,6 +96,8 @@ is `user:pass`. Non-2xx answers are retried; `GET /__admin/webhooks`, `…/event
89
96
  | `POST /__admin/clicks` | `{ref_token}` → `{tid, promoterId}`: a click on the promoter's link. |
90
97
  | `GET /__admin/referrals` | Tracked signups. |
91
98
  | `POST /__admin/referrals/:id/convert` | `{saleAmount?}`: the lead paid; credits the promoter (percent reward × amount) and posts the webhook. |
99
+ | `POST /__admin/commissions` | Seed a commission against an existing `{promoter_campaign_id, amount, unit?, status?, fulfilled?, is_paid?, referral_id?, sale_amount?, event_id?}`. Defaults: approved, points, unfulfilled/unpaid. A referral must belong to that promoter and campaign. |
100
+ | `POST /__admin/promo-codes` | Seed `{promo_code, promoter_campaign_id}` against an existing promoter campaign for sale attribution tests. |
92
101
  | `GET\|PUT /__admin/settings` | `{website?, defaultCampaignId?, autoConvert?, campaigns?}` (campaigns carry `referralRewards` / `promoterRewards` with `coupon`, `amount`, `unit`, `per_of_sale`). The default campaign's referral coupon is `ACME50`. |
93
102
 
94
103
  Fault presets (`POST /__admin/faults {"preset": "<name>", "count"?: n}`; `GET /__admin/faults/presets`):
@@ -97,6 +106,35 @@ Fault presets (`POST /__admin/faults {"preset": "<name>", "count"?: n}`; `GET /_
97
106
  `unauthorized`, `rate_limited`, `server_error`, `connection_drop`, `webhook_duplicate`,
98
107
  `webhook_drop`.
99
108
 
109
+ Commission reconciliation follows FirstPromoter's [published contract](https://github.com/firstpromoter/docs/blob/d4e9e6f16bf4801c524508d2809a425ea6419d7d/api-reference-v2/api-admin/commissions/openapi-v2-commissions.json):
110
+ `GET /v2/company/commissions` returns a bare array, newest first, with `q`, repeated `ids[]`,
111
+ `page` / `per_page` (1 / 20 by default, maximum 100), and filters for `status`, nonmonetary
112
+ `fulfilled=yes|no`, monetary `paid=yes|no`, `promoter_id`, `campaign_id`, amount / sale-amount
113
+ ranges and creation-date ranges. `POST …/commissions/mark_fulfilled` fulfills nonmonetary
114
+ commissions; `DELETE …/commissions/destroy` deletes selected commissions. Both take `{ids}`.
115
+ Batches of at most five IDs return 200/completed; larger batches return 202/pending. In the
116
+ mock they move to in_progress after the clock advances and complete at 1,000 ms, on the next
117
+ authenticated API call. The batch collections and pending work participate in reset and snapshots.
118
+ `GET …/batch_processes` and `…/batch_processes/progress` list unfinished work by default
119
+ (`filters[status]` selects another status); `GET …/batch_processes/{id}` returns counts and
120
+ processing errors. `batch_partial_failure` fails the first selected item while processing the
121
+ others. Timing, missing-ID/monetary-item error text, and this preset are synthetic controls;
122
+ they are not claims about the vendor's worker timing or exact error messages. Fulfillment is
123
+ stored separately from the vendor's `is_paid` monetary field.
124
+
125
+ `POST /v2/track/sale` follows the vendor's [sale contract](https://github.com/firstpromoter/docs/blob/d4e9e6f16bf4801c524508d2809a425ea6419d7d/api-reference-v2/api-admin/tracking-api/openapi-v2-tracking.json):
126
+ `{event_id, amount, email|uid, currency?, plan?, promo_code?, ref_id?, tid?, skip_email_notification?}`
127
+ records a positive integer amount in minor units against a tracked referral. The first configured
128
+ campaign reward supplies an approved commission; percent rewards are rounded to the nearest
129
+ minor unit, and flat rewards use their configured amount. Cash rewards also credit the existing
130
+ promoter balance; nonmonetary rewards do not. The response includes the referral, amount and
131
+ linked commissions, visible in the commission collection. Replaying an event ID returns the
132
+ documented 409 without another credit, commission or webhook. Unknown referrals, archived
133
+ promoters and unmatched supplied attribution tokens return the documented 404 `not_found` shape.
134
+ Codes must be seeded through the admin control; tokens must belong to the referral's promoter
135
+ campaign. All validation precedes sale/commission/balance writes; snapshots/reset include event
136
+ deduplication. A successful sale preserves the existing conversion webhook behavior.
137
+
100
138
  ### Namespaces
101
139
 
102
140
  `x-mockingbird-namespace`, a `/__admin/ns/<name>` prefix in `FIRST_PROMOTER_API_URL`, or by API key:
@@ -109,8 +147,15 @@ Fault presets (`POST /__admin/faults {"preset": "<name>", "count"?: n}`; `GET /_
109
147
  branches on `ok` / 404, which the mock gets right.
110
148
  - The v1 API our EMR backend still calls (`/v1/promoters/*`, `/v1/track/signup`,
111
149
  `/v1/reports/campaigns`); the catalog scopes this mock to v2.
112
- - Sales, refunds, commissions and payouts beyond the single `convert` step; fraud checks;
113
- promo codes; the hosted affiliate portal behind the iframe token.
150
+ - Refunds, standalone commission creation/editing/approval, cash payouts and commission filters
151
+ beyond those listed above; fraud checks;
152
+ public promo-code provisioning; the hosted affiliate portal behind the iframe token.
153
+ - Sale tracking requires an existing referral (the vendor's one-step signup bypass is unmodelled).
154
+ Currency is recorded without foreign-exchange conversion; plan-specific rewards, quantity/MRR
155
+ calculations, multiple reward tiers, split commissions and notification emails are unmodelled.
156
+ Commission rounding and immediate approval are deterministic mock policies, not live-verified
157
+ campaign policy. The default campaign reward remains 10 percent, as before.
158
+ - Referral editing/deletion, username/website profile provisioning, cancelled-date filters and split attribution.
114
159
  - Promoter ids are sequential from 4800001 per namespace.
115
160
 
116
161
  ## API
package/SUPPORT.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Generated from `openapi.yaml`; do not edit by hand.
4
4
 
5
- - operations in spec: **7**
6
- - supported by the mock: **7**
7
- - parity enabled: **7**
5
+ - operations in spec: **16**
6
+ - supported by the mock: **16**
7
+ - parity enabled: **16**
8
8
 
9
9
  | operationId | route | mock | parity | notes |
10
10
  | --- | --- | --- | --- | --- |
@@ -15,3 +15,12 @@ Generated from `openapi.yaml`; do not edit by hand.
15
15
  | `GetPromoter` | `GET /v2/company/promoters/{id}` | ✅ supported | ✅ | |
16
16
  | `UpdatePromoter` | `PUT /v2/company/promoters/{id}` | ✅ supported | ⚠️ unsafe (opt-in) | |
17
17
  | `IframeLogin` | `POST /v2/promoters/iframe_login` | ✅ supported | ✅ | |
18
+ | `ListReferrals` | `GET /v2/company/referrals` | ✅ supported | ✅ | |
19
+ | `GetReferral` | `GET /v2/company/referrals/{id}` | ✅ supported | ✅ | |
20
+ | `ListCommissions` | `GET /v2/company/commissions` | ✅ supported | ✅ | |
21
+ | `FulfillCommissions` | `POST /v2/company/commissions/mark_fulfilled` | ✅ supported | ⚠️ unsafe (opt-in) | |
22
+ | `DestroyCommissions` | `DELETE /v2/company/commissions/destroy` | ✅ supported | ⚠️ unsafe (opt-in) | |
23
+ | `ListBatchProcesses` | `GET /v2/company/batch_processes` | ✅ supported | ✅ | |
24
+ | `BatchProcessProgress` | `GET /v2/company/batch_processes/progress` | ✅ supported | ✅ | |
25
+ | `GetBatchProcess` | `GET /v2/company/batch_processes/{id}` | ✅ supported | ✅ | |
26
+ | `TrackSale` | `POST /v2/track/sale` | ✅ supported | ⚠️ unsafe (opt-in) | |