Skip to content

Add workflows network layer for multipage paywalls#6557

Open
vegaro wants to merge 27 commits intomainfrom
feat/workflows-network-layer
Open

Add workflows network layer for multipage paywalls#6557
vegaro wants to merge 27 commits intomainfrom
feat/workflows-network-layer

Conversation

@vegaro
Copy link
Copy Markdown
Member

@vegaro vegaro commented Apr 6, 2026

Summary

iOS equivalent of RevenueCat/purchases-android#3300.

Adds the networking layer needed to fetch multipage paywall workflows from the RevenueCat backend.

  • New endpoint paths: getWorkflows(appUserID:) and getWorkflow(appUserID:workflowId:) in HTTPRequestPath
  • Response models: WorkflowsListResponse, WorkflowSummary, PublishedWorkflow, WorkflowStep, WorkflowScreen, WorkflowTriggerAction, WorkflowFetchResult
  • CDN handling: WorkflowDetailProcessor normalises the two response shapes — inline (data embedded in response) and use_cdn (fetch JSON from CDN URL).
  • Operations: GetWorkflowsOperation and GetWorkflowOperation as CacheableNetworkOperation subclasses with callback deduplication

Note

Medium Risk
Adds new backend endpoints and response processing that can fetch workflow JSON from arbitrary CDN URLs, impacting networking behavior and error handling. Risk is moderated by heavy unit test and snapshot coverage plus request deduplication via callback caches.

Overview
Adds a new WorkflowsAPI to fetch multipage paywall workflows from the backend via new GET /v1/subscribers/{appUserID}/workflows and GET /v1/subscribers/{appUserID}/workflows/{workflowId} paths, wired into Backend.

Introduces workflow response models plus GetWorkflowsOperation/GetWorkflowOperation with callback-cache deduping and app-user ID validation. For workflow detail, adds WorkflowDetailProcessor to normalize inline vs use_cdn envelopes, including a new HTTPClient.fetchRawData(from:) helper to fetch workflow JSON from CDN URLs using the SDK’s configured URLSession.

Updates tests with new mocks, decoding/processor unit tests, and backend request snapshot coverage for the new endpoints.

Reviewed by Cursor Bugbot for commit e7b8a9f. Bugbot is set up for automated code reviews on this repo. Configure here.

- Add `getWorkflows` and `getWorkflow` endpoint paths
- Add `WorkflowsListResponse` and `PublishedWorkflow` response models
- Add `WorkflowDetailProcessor` to handle `inline`/`use_cdn` response actions
- Add `WorkflowCdnFetcher` protocol and `DirectWorkflowCdnFetcher` implementation
- Add `GetWorkflowsOperation` and `GetWorkflowOperation` cacheable network operations
- Add `WorkflowsAPI` facade and wire into `Backend`
- Add unit tests for all new components

iOS equivalent of RevenueCat/purchases-android#3300

Made-with: Cursor
@vegaro vegaro added the pr:feat A new feature label Apr 6, 2026
@emerge-tools
Copy link
Copy Markdown

emerge-tools bot commented Apr 6, 2026

4 builds increased size

Name Version Download Change Install Change Approval
RevenueCat
com.revenuecat.PaywallsTester
1.0 (1) 17.5 MB ⬆️ 86.0 kB (0.49%) 62.8 MB ⬆️ 377.8 kB (0.61%) N/A
BinarySizeTest
com.revenuecat.binary-size-test.local-source
1.0 (1) 3.9 MB ⬆️ 29.6 kB (0.76%) 11.8 MB ⬆️ 93.1 kB (0.8%) ⏳ Needs approval
BinarySizeTest
com.revenuecat.binary-size-test.cocoapods
1.0 (1) 5.9 MB ⬆️ 44.2 kB (0.75%) 26.2 MB ⬆️ 205.3 kB (0.79%) ⏳ Needs approval
BinarySizeTest
com.revenuecat.binary-size-test.spm
1.0 (1) 4.0 MB ⬆️ 30.7 kB (0.77%) 10.3 MB ⬆️ 84.5 kB (0.83%) ⏳ Needs approval

RevenueCat 1.0 (1)
com.revenuecat.PaywallsTester

⚖️ Compare build
⏱️ Analyze build performance

Total install size change: ⬆️ 377.8 kB (0.61%)
Total download size change: ⬆️ 86.0 kB (0.49%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 121.2 kB
DYLD.Exports ⬆️ 9.5 kB
Code Signature ⬆️ 9.4 kB
📝 RevenueCat.WorkflowsAPI.WorkflowsAPI ⬆️ 4.6 kB
RevenueCat.WebBillingAPI.WebBillingAPI ⬇️ -1.4 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.local-source

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 93.1 kB (0.8%)
Total download size change: ⬆️ 29.6 kB (0.76%)

Largest size changes

Item Install Size Change
📝 RevenueCat.WorkflowScreen.value witness ⬆️ 10.1 kB
DYLD.String Table ⬆️ 10.0 kB
📝 RevenueCat.PublishedWorkflow.__derived_struct_equals ⬆️ 7.7 kB
RevenueCat.UIConfig.Equatable ⬇️ -4.9 kB
📝 RevenueCat.WorkflowScreen.__derived_struct_equals ⬆️ 4.6 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 205.3 kB (0.79%)
Total download size change: ⬆️ 44.2 kB (0.75%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 78.0 kB
📝 RevenueCat.WorkflowScreen.value witness ⬆️ 10.1 kB
📝 RevenueCat.PublishedWorkflow.__derived_struct_equals ⬆️ 7.5 kB
RevenueCat.UIConfig.Equatable ⬇️ -4.8 kB
Code Signature ⬆️ 4.8 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 84.5 kB (0.83%)
Total download size change: ⬆️ 30.7 kB (0.77%)

Largest size changes

Item Install Size Change
📝 RevenueCat.WorkflowScreen.value witness ⬆️ 10.1 kB
📝 RevenueCat.PublishedWorkflow.__derived_struct_equals ⬆️ 7.7 kB
RevenueCat.UIConfig.Equatable ⬇️ -4.9 kB
📝 RevenueCat.WorkflowScreen.__derived_struct_equals ⬆️ 4.6 kB
RevenueCat.PaywallComponent.StackComponent.StackComponent ⬇️ -4.0 kB
View Treemap

Image of diff


🛸 Powered by Emerge Tools

Comment trigger: Size diff threshold of 100.00kB exceeded

vegaro added 6 commits April 6, 2026 17:39
- Add WorkflowTrigger struct (name, type, action_id, component_id)
- Add triggers, outputs, and metadata fields to WorkflowStep
- Add metadata field to PublishedWorkflow
- Remove value field from WorkflowTriggerAction (backend uses step_id only)

Made-with: Cursor
- Replace value/resolvedTargetStepId assertions with stepId
- Remove testDecodeWorkflowTriggerActionValueTakesPrecedence (value field removed)
- Add testDecodeWorkflowTrigger for new WorkflowTrigger struct
- Add testDecodePublishedWorkflowWithMetadata
- Update testDecodeWorkflowStepDefaults to cover triggers, outputs, metadata
- Add testDecodeWorkflowStepMatchingActualBackendResponse with real backend payload

Made-with: Cursor
@vegaro vegaro marked this pull request as ready for review April 7, 2026 09:59
@vegaro vegaro requested a review from a team as a code owner April 7, 2026 09:59
@vegaro vegaro requested a review from facumenzella April 7, 2026 09:59
vegaro added 2 commits April 7, 2026 12:09
…o callbacks

CDN fetch and JSON decoding were running once per deduplicated callback.
Compute the Result<WorkflowFetchResult, BackendError> once outside the
performOnAllItemsAndRemoveFromCache loop, matching the pattern used by
GetOfferingsOperation and other operations in the codebase.

Made-with: Cursor
…purchases-ios into feat/workflows-network-layer
vegaro added 2 commits April 7, 2026 12:40
…y errors correctly

- Replace Data(contentsOf:) with URLSession.shared.dataTask + DispatchSemaphore
  in DirectWorkflowCdnFetcher; gets URLSession timeout, HTTP status validation,
  and proper network stack semantics
- Add WorkflowDetailProcessingError.cdnFetchFailed typed error so CDN I/O
  failures are distinguishable from envelope parsing failures
- Catch cdnFetchFailed in GetWorkflowOperation and map to NetworkError.networkError
  instead of NetworkError.decoding, fixing misleading error classification
- Update WorkflowDetailProcessorTests to assert the typed error is thrown

Made-with: Cursor
…gContinuation

- Make WorkflowCdnFetcher.fetchCompiledWorkflowData async throws; use
  withCheckedThrowingContinuation to bridge URLSession.dataTask into async,
  avoiding any thread-blocking
- Make WorkflowDetailProcessor.process async throws to propagate async
- Bridge into async in GetWorkflowOperation via Task {}; completion() is
  called inside the Task after CDN fetch and decoding complete
- Update WorkflowDetailProcessorTests to async throws with await

Made-with: Cursor
Avoids Task{} in GetWorkflowOperation and keeps all operations calling
completion() synchronously from within the HTTP callback, matching every
other operation in the codebase.

- WorkflowCdnFetcher.fetchCompiledWorkflowData now takes a completion handler;
  DirectWorkflowCdnFetcher uses URLSession.dataTask (non-blocking, no semaphore)
- WorkflowDetailProcessor.process now takes a completion handler; inline action
  completes synchronously, use_cdn fans out to the fetcher callback
- GetWorkflowOperation splits into getWorkflow/handleResponse/backendResult/
  distribute helpers to stay within line-length limits
- WorkflowDetailProcessorTests updated to use waitUntilValue pattern

Made-with: Cursor
Space-separated appUserID+workflowId could collide (e.g. user 'a b' + workflow 'c'
== user 'a' + workflow 'b c'). Use newline as delimiter, matching the precedent
set by GetWebBillingProductsOperation.

Made-with: Cursor
Copy link
Copy Markdown
Member

@ajpallares ajpallares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't have all the context yet, but I have some early comments

.postOfferForSigning,
.postRedeemWebPurchase,
.getCustomerCenterConfig,
.getWorkflow,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it deliberate to have getWorkflows supportsSignatureVerification --> true while getWorkflow is false?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the backend only supports signature verification for the endpoint that lists workflows

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to bring it up because it looks like an oversight to me

@vegaro vegaro requested a review from a team as a code owner April 10, 2026 08:18
@RevenueCat-Danger-Bot
Copy link
Copy Markdown

RevenueCat-Danger-Bot commented Apr 10, 2026

1 Warning
⚠️ This PR increases the size of the repo by more than 100.00 KB (increased by 111.75 KB).

Generated by 🚫 Danger

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 30001f0. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:feat A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants