Generating new test snapshots for feat/workflows-network-layer - ios-16#6586
Conversation
Generated by 🚫 Danger |
4 builds increased size
RevenueCat 1.0 (1)
|
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 121.2 kB |
| DYLD.Exports | ⬆️ 9.5 kB |
| Code Signature | ⬆️ 9.0 kB |
| 📝 RevenueCat.WorkflowsAPI.WorkflowsAPI | ⬆️ 4.6 kB |
| RevenueCat.WebBillingAPI.WebBillingAPI | ⬇️ -1.4 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.local-source
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 96.9 kB (0.84%)
Total download size change: ⬆️ 31.3 kB (0.81%)
Largest size changes
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 10.0 kB |
| 📝 RevenueCat.WorkflowScreen.value witness | ⬆️ 10.0 kB |
| 📝 RevenueCat.PublishedWorkflow.__derived_struct_equals | ⬆️ 7.6 kB |
| RevenueCat.UIConfig.Equatable | ⬇️ -4.9 kB |
| 📝 RevenueCat.WorkflowScreen.__derived_struct_equals | ⬆️ 4.6 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods
⚖️ Compare build
⏱️ Analyze build performance
Total install size change: ⬆️ 205.2 kB (0.8%)
Total download size change: ⬆️ 45.4 kB (0.77%)
Largest size changes
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 78.0 kB |
| 📝 RevenueCat.WorkflowScreen.value witness | ⬆️ 10.0 kB |
| 📝 RevenueCat.PublishedWorkflow.__derived_struct_equals | ⬆️ 7.5 kB |
| RevenueCat.UIConfig.Equatable | ⬇️ -4.8 kB |
| Code Signature | ⬆️ 4.8 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 80.2 kB (0.79%)
Total download size change: ⬆️ 30.2 kB (0.76%)
Largest size changes
| Item | Install Size Change |
|---|---|
| 📝 RevenueCat.WorkflowScreen.value witness | ⬆️ 10.0 kB |
| 📝 RevenueCat.PublishedWorkflow.__derived_struct_equals | ⬆️ 7.6 kB |
| RevenueCat.UIConfig.Equatable | ⬇️ -4.9 kB |
| 📝 RevenueCat.WorkflowScreen.__derived_struct_equals | ⬆️ 4.6 kB |
| RevenueCat.PaywallComponent.StackComponent.StackComponent | ⬇️ -4.0 kB |
🛸 Powered by Emerge Tools
Comment trigger: Size diff threshold of 100.00kB exceeded
* Add workflows network layer for multipage paywalls - 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 * fix xcodeproj * reset Package.resolved * Update WorkflowStep models to match actual backend response - 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 * Update WorkflowResponseTests to match updated models - 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 * Disable file_length lint rule in HTTPRequestPath.swift Made-with: Cursor * Fix GetWorkflowOperation to compute result once before distributing to 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 * Fix CDN fetcher: use URLSession instead of Data(contentsOf:), classify 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 * Replace semaphore CDN fetch with async/await using withCheckedThrowingContinuation - 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 * Make CDN fetcher and processor completion-handler based for consistency 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 * Fix ambiguous cache key delimiter in GetWorkflowOperation 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 * PR comments * remove cdn fetcher * fix response in BackendGetWorkflowsTests.swift * fix WorkflowResponseTests * fix error * [skip ci] Generating new test snapshots (#6584) * [skip ci] Generating new test snapshots (#6585) * [skip ci] Generating new test snapshots (#6586) * [skip ci] Generating new test snapshots (#6587) * [skip ci] Generating new test snapshots (#6588) * [skip ci] Generating new test snapshots (#6589) * [skip ci] Generating new test snapshots (#6590) * Test CDN mock is not re-assignable per test * [skip ci] Generating new test snapshots (#6597) * [skip ci] Generating new test snapshots (#6598) * [skip ci] Generating new test snapshots (#6599) * [skip ci] Generating new test snapshots (#6600) * [skip ci] Generating new test snapshots (#6601) * [skip ci] Generating new test snapshots (#6602) * [skip ci] Generating new test snapshots (#6603) * getWorkflow is signed * add type parameter * add response verification for CDN response * remove workflows list * add value to WorkflowTriggerAction * step id * hash and filerepo * missingCdnHash * linter and project * fix project * revert Package.resolved * @unchecked Sendable * use hash in generateOrGetCachedFileURL * fix compilation * skip responseVerificationMode in cdn * change basePath of caches * remove reserialization * Use explicit type in GetWorkflowOperation.createFactory for greppability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix swiftlint identifier_name violation in WorkflowDetailProcessorTests Rename short variable `d` to `doubleValue` in two `if case .double(let d)` patterns to satisfy the identifier_name rule requiring names >= 3 characters. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * remove default FileRepositoryType * fix project * fix test * test preserves camel case * Generating new test snapshots for `feat/workflows-network-layer` - ios-15 (#6654) * Generating new test snapshots for `feat/workflows-network-layer` - ios-14 (#6656) --------- Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com> Co-authored-by: Facundo Menzella <facumenzella@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Facundo Menzella <facumenzella@users.noreply.github.com>
* Add workflows network layer for multipage paywalls - 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 * fix xcodeproj * reset Package.resolved * Update WorkflowStep models to match actual backend response - 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 * Update WorkflowResponseTests to match updated models - 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 * Disable file_length lint rule in HTTPRequestPath.swift Made-with: Cursor * Fix GetWorkflowOperation to compute result once before distributing to 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 * Fix CDN fetcher: use URLSession instead of Data(contentsOf:), classify 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 * Replace semaphore CDN fetch with async/await using withCheckedThrowingContinuation - 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 * Make CDN fetcher and processor completion-handler based for consistency 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 * Fix ambiguous cache key delimiter in GetWorkflowOperation 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 * PR comments * remove cdn fetcher * fix response in BackendGetWorkflowsTests.swift * fix WorkflowResponseTests * fix error * [skip ci] Generating new test snapshots (#6584) * [skip ci] Generating new test snapshots (#6585) * [skip ci] Generating new test snapshots (#6586) * [skip ci] Generating new test snapshots (#6587) * [skip ci] Generating new test snapshots (#6588) * [skip ci] Generating new test snapshots (#6589) * [skip ci] Generating new test snapshots (#6590) * Test CDN mock is not re-assignable per test * [skip ci] Generating new test snapshots (#6597) * [skip ci] Generating new test snapshots (#6598) * [skip ci] Generating new test snapshots (#6599) * [skip ci] Generating new test snapshots (#6600) * [skip ci] Generating new test snapshots (#6601) * [skip ci] Generating new test snapshots (#6602) * [skip ci] Generating new test snapshots (#6603) * getWorkflow is signed * add type parameter * add response verification for CDN response * remove workflows list * add value to WorkflowTriggerAction * step id * hash and filerepo * missingCdnHash * linter and project * fix project * revert Package.resolved * @unchecked Sendable * use hash in generateOrGetCachedFileURL * fix compilation * skip responseVerificationMode in cdn * change basePath of caches * Add workflow-based paywall resolution (iOS parity with Android #3350) Implements the workflows endpoint so paywalls can be resolved from a workflow document rather than the offerings cache, gated behind the ENABLE_WORKFLOWS_ENDPOINT compile flag. Validates the step→screen→ offeringId chain and maps the workflow screen into Offering.PaywallComponents using the existing V2 rendering path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add tests for workflow networking layer and WorkflowScreenMapper BackendGetWorkflowTests covers HTTP call, request caching, per-user and per-workflow-ID deduplication, error propagation, empty appUserID, and full response decoding. WorkflowScreenMapperTests verifies all PaywallComponentsData fields and the UIConfig are mapped correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * remove reserialization * Use explicit type in GetWorkflowOperation.createFactory for greppability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Use explicit type in GetWorkflowOperation.createFactory for greppability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix lint errors and refactor workflow offering resolution into PaywallViewConfiguration - Add swiftlint:disable comments for _revision identifier name in WorkflowsResponse.swift - Add missing_docs disable in WorkflowsResponse.swift (all @_spi(Internal) types) - Add file_length disable in Offering.swift - Fix identifier name 'd' → 'doubleValue' in WorkflowDetailProcessorTests.swift - Move workflow offering resolution from PaywallView into PaywallViewConfiguration.resolveOfferingOrThrow() - Add cachedInitialOffering() to PaywallViewConfiguration.Content - Add PaywallViewConfigurationTests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix swiftlint identifier_name violation in WorkflowDetailProcessorTests Rename short variable `d` to `doubleValue` in two `if case .double(let d)` patterns to satisfy the identifier_name rule requiring names >= 3 characters. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Inject PaywallPurchasesType into offering resolution; remove dead code - Add offerings(), cachedOfferings, and workflow() to PaywallPurchasesType so PaywallViewConfiguration.Content no longer calls Purchases.shared directly - Thread purchases through cachedInitialOffering/resolveOffering/resolveOfferingOrThrow and all private helpers; callers pass purchaseHandler.purchasesInstance - Expose purchasesInstance on PurchaseHandler for call sites - Add stubs to NotConfiguredPurchases, LoadingPaywallPurchases, and MockPurchases (MockPurchases gets offeringsBlock/workflowBlock for test injection) - Remove dead WorkflowDetailProcessingError.missingInlineData case - Replace manual JSONSerialization parseEnvelope with Data.asJSONDictionary() - Collapse double #if nesting into single compound condition - Remove WHAT doc comment from WorkflowDetailProcessor - Refactor resolveOffering() to delegate to resolveOfferingOrThrow() - Parallelize workflow + offerings fetches with async let Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Move offering resolution from Content to PurchaseHandler Resolving an offering requires a purchases instance, so it belongs on PurchaseHandler rather than as a method on the Content enum that takes purchases as a parameter. purchasesInstance accessor removed. Also fix MockPurchases.map() to forward offeringsBlock, workflowBlock, and cachedOfferings to the mapped instance, and simplify PaywallViewConfigurationTests to use MockPurchases directly instead of configuring a real Purchases singleton. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add clarifying comment to workflow(forOfferingIdentifier:) explaining parameter naming Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix CI failures: remove duplicate switch cases and add @_spi(Internal) to test imports - Remove duplicate .getWorkflow cases in HTTPRequestPath.swift switches (auto-merge artifact that caused duplicate_conditions lint violations) - Add @_spi(Internal) to @testable imports in three unit test files so they can access WorkflowFetchResult, PublishedWorkflow, and WorkflowStep which are now @_spi(Internal) public Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix @_spi access in WorkflowDetailProcessorTests WorkflowResponseTests already had @_spi(Internal) @testable import RevenueCat; WorkflowDetailProcessorTests was missing the @_spi annotation, causing 'id', 'steps', and 'initialStepId' to be inaccessible on PublishedWorkflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix MockWorkflowsAPI.swift missing from StoreKitUnitTests and UnitTests targets The PBXBuildFile entries for DB7EA77F2F9764F700BCC082 and DB7EA7802F9764F700BCC082 were referenced in the StoreKitUnitTests and UnitTests source phases but never defined, causing MockWorkflowsAPI to be missing at compile time and MockBackend.swift to fail with 'cannot find MockWorkflowsAPI in scope'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add offering_identifier field to WorkflowScreen for parity with Android Android PR #3350 split offering_id (internal ID) from offering_identifier (human-readable identifier used for lookup). iOS was only decoding offering_id and using it for the offering lookup, which would fail if the workflow response sends the public identifier in offering_identifier. - Add offeringIdentifier (from offering_identifier) to WorkflowScreen - Update PurchaseHandler to prefer offeringIdentifier, falling back to offeringId - Fix typo: workflow.screelns -> workflow.screens - Add decode tests for both offering fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix WorkflowResponseTests: add missing padding field to stack component fixtures Stack component decoding requires a padding field; test JSON fixtures were missing it causing keyNotFound decode errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix WorkflowResponseTests: add missing margin field to stack component fixtures Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Replace ENABLE_WORKFLOWS_ENDPOINT compile flag with runtime argument check The -EnableWorkflowsEndpoint launch argument replaces the compile-time flag, allowing workflow resolution to be toggled without rebuilding. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add Workflow presentation mode to PaywallsTester Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove offeringId shim, allow no-paywall offerings to open as workflows - Drop WorkflowScreen.offeringId / offering_id CodingKey (Android already uses offering_identifier exclusively — aligns both platforms) - Simplify PurchaseHandler to use screen.offeringIdentifier directly - No-paywall offerings in PaywallsTester now render as tappable rows (workflow mode) instead of plain read-only text, with a context menu restricted to the Workflow option Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Rename WorkflowFetchResult to WorkflowDataResult, extract ProcessInfo extension Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix project --------- Co-authored-by: Cesar de la Vega <664544+vegaro@users.noreply.github.com> Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add workflows network layer for multipage paywalls - 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 * fix xcodeproj * reset Package.resolved * Update WorkflowStep models to match actual backend response - 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 * Update WorkflowResponseTests to match updated models - 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 * Disable file_length lint rule in HTTPRequestPath.swift Made-with: Cursor * Fix GetWorkflowOperation to compute result once before distributing to 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 * Fix CDN fetcher: use URLSession instead of Data(contentsOf:), classify 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 * Replace semaphore CDN fetch with async/await using withCheckedThrowingContinuation - 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 * Make CDN fetcher and processor completion-handler based for consistency 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 * Fix ambiguous cache key delimiter in GetWorkflowOperation 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 * PR comments * remove cdn fetcher * fix response in BackendGetWorkflowsTests.swift * fix WorkflowResponseTests * fix error * [skip ci] Generating new test snapshots (#6584) * [skip ci] Generating new test snapshots (#6585) * [skip ci] Generating new test snapshots (#6586) * [skip ci] Generating new test snapshots (#6587) * [skip ci] Generating new test snapshots (#6588) * [skip ci] Generating new test snapshots (#6589) * [skip ci] Generating new test snapshots (#6590) * Test CDN mock is not re-assignable per test * [skip ci] Generating new test snapshots (#6597) * [skip ci] Generating new test snapshots (#6598) * [skip ci] Generating new test snapshots (#6599) * [skip ci] Generating new test snapshots (#6600) * [skip ci] Generating new test snapshots (#6601) * [skip ci] Generating new test snapshots (#6602) * [skip ci] Generating new test snapshots (#6603) * getWorkflow is signed * add type parameter * add response verification for CDN response * remove workflows list * add value to WorkflowTriggerAction * step id * hash and filerepo * missingCdnHash * linter and project * fix project * revert Package.resolved * @unchecked Sendable * use hash in generateOrGetCachedFileURL * fix compilation * skip responseVerificationMode in cdn * change basePath of caches * Add workflow-based paywall resolution (iOS parity with Android #3350) Implements the workflows endpoint so paywalls can be resolved from a workflow document rather than the offerings cache, gated behind the ENABLE_WORKFLOWS_ENDPOINT compile flag. Validates the step→screen→ offeringId chain and maps the workflow screen into Offering.PaywallComponents using the existing V2 rendering path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add tests for workflow networking layer and WorkflowScreenMapper BackendGetWorkflowTests covers HTTP call, request caching, per-user and per-workflow-ID deduplication, error propagation, empty appUserID, and full response decoding. WorkflowScreenMapperTests verifies all PaywallComponentsData fields and the UIConfig are mapped correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * remove reserialization * Use explicit type in GetWorkflowOperation.createFactory for greppability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Use explicit type in GetWorkflowOperation.createFactory for greppability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix lint errors and refactor workflow offering resolution into PaywallViewConfiguration - Add swiftlint:disable comments for _revision identifier name in WorkflowsResponse.swift - Add missing_docs disable in WorkflowsResponse.swift (all @_spi(Internal) types) - Add file_length disable in Offering.swift - Fix identifier name 'd' → 'doubleValue' in WorkflowDetailProcessorTests.swift - Move workflow offering resolution from PaywallView into PaywallViewConfiguration.resolveOfferingOrThrow() - Add cachedInitialOffering() to PaywallViewConfiguration.Content - Add PaywallViewConfigurationTests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix swiftlint identifier_name violation in WorkflowDetailProcessorTests Rename short variable `d` to `doubleValue` in two `if case .double(let d)` patterns to satisfy the identifier_name rule requiring names >= 3 characters. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Inject PaywallPurchasesType into offering resolution; remove dead code - Add offerings(), cachedOfferings, and workflow() to PaywallPurchasesType so PaywallViewConfiguration.Content no longer calls Purchases.shared directly - Thread purchases through cachedInitialOffering/resolveOffering/resolveOfferingOrThrow and all private helpers; callers pass purchaseHandler.purchasesInstance - Expose purchasesInstance on PurchaseHandler for call sites - Add stubs to NotConfiguredPurchases, LoadingPaywallPurchases, and MockPurchases (MockPurchases gets offeringsBlock/workflowBlock for test injection) - Remove dead WorkflowDetailProcessingError.missingInlineData case - Replace manual JSONSerialization parseEnvelope with Data.asJSONDictionary() - Collapse double #if nesting into single compound condition - Remove WHAT doc comment from WorkflowDetailProcessor - Refactor resolveOffering() to delegate to resolveOfferingOrThrow() - Parallelize workflow + offerings fetches with async let Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Move offering resolution from Content to PurchaseHandler Resolving an offering requires a purchases instance, so it belongs on PurchaseHandler rather than as a method on the Content enum that takes purchases as a parameter. purchasesInstance accessor removed. Also fix MockPurchases.map() to forward offeringsBlock, workflowBlock, and cachedOfferings to the mapped instance, and simplify PaywallViewConfigurationTests to use MockPurchases directly instead of configuring a real Purchases singleton. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add clarifying comment to workflow(forOfferingIdentifier:) explaining parameter naming Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix CI failures: remove duplicate switch cases and add @_spi(Internal) to test imports - Remove duplicate .getWorkflow cases in HTTPRequestPath.swift switches (auto-merge artifact that caused duplicate_conditions lint violations) - Add @_spi(Internal) to @testable imports in three unit test files so they can access WorkflowFetchResult, PublishedWorkflow, and WorkflowStep which are now @_spi(Internal) public Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix @_spi access in WorkflowDetailProcessorTests WorkflowResponseTests already had @_spi(Internal) @testable import RevenueCat; WorkflowDetailProcessorTests was missing the @_spi annotation, causing 'id', 'steps', and 'initialStepId' to be inaccessible on PublishedWorkflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix MockWorkflowsAPI.swift missing from StoreKitUnitTests and UnitTests targets The PBXBuildFile entries for DB7EA77F2F9764F700BCC082 and DB7EA7802F9764F700BCC082 were referenced in the StoreKitUnitTests and UnitTests source phases but never defined, causing MockWorkflowsAPI to be missing at compile time and MockBackend.swift to fail with 'cannot find MockWorkflowsAPI in scope'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add offering_identifier field to WorkflowScreen for parity with Android Android PR #3350 split offering_id (internal ID) from offering_identifier (human-readable identifier used for lookup). iOS was only decoding offering_id and using it for the offering lookup, which would fail if the workflow response sends the public identifier in offering_identifier. - Add offeringIdentifier (from offering_identifier) to WorkflowScreen - Update PurchaseHandler to prefer offeringIdentifier, falling back to offeringId - Fix typo: workflow.screelns -> workflow.screens - Add decode tests for both offering fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix WorkflowResponseTests: add missing padding field to stack component fixtures Stack component decoding requires a padding field; test JSON fixtures were missing it causing keyNotFound decode errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix WorkflowResponseTests: add missing margin field to stack component fixtures Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Replace ENABLE_WORKFLOWS_ENDPOINT compile flag with runtime argument check The -EnableWorkflowsEndpoint launch argument replaces the compile-time flag, allowing workflow resolution to be toggled without rebuilding. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add Workflow presentation mode to PaywallsTester Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove offeringId shim, allow no-paywall offerings to open as workflows - Drop WorkflowScreen.offeringId / offering_id CodingKey (Android already uses offering_identifier exclusively — aligns both platforms) - Simplify PurchaseHandler to use screen.offeringIdentifier directly - No-paywall offerings in PaywallsTester now render as tappable rows (workflow mode) instead of plain read-only text, with a context menu restricted to the Workflow option Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Rename WorkflowFetchResult to WorkflowDataResult, extract ProcessInfo extension Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix project * Fix Customer Center showing active-subscriber management options to expired users hasActiveSubscription was checking subscriptionsSection non-emptiness, but that section is intentionally populated with the most recent expired subscription when there are no active ones (via loadMostRecentExpiredTransaction). The fix checks whether any entry in the section is non-expired, which correctly answers "does this customer have an active subscription?" regardless of how many subscriptions exist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cesar de la Vega <664544+vegaro@users.noreply.github.com> Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>




Requested by @vegaro for feat/workflows-network-layer
Note
Low Risk
Adds new test snapshot fixtures only; no production code changes. Risk is limited to potential snapshot brittleness/CI diffs if request headers change again.
Overview
Adds new iOS 16 snapshot JSON fixtures for
BackendGetWorkflowsTestsandBackendGetWorkflowTests, capturing the expected GET requests (headers + URLs) for listing workflows and fetching a single workflow.This updates snapshot coverage for caching, inline workflow responses, enrolled variants, and error propagation scenarios without changing runtime behavior.
Reviewed by Cursor Bugbot for commit acc063a. Bugbot is set up for automated code reviews on this repo. Configure here.