Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
81e6377
Fix build on Xcode 26.0.1: disambiguate fontScale arithmetic
jakemor Aug 16, 2026
7a81787
Keep subscribers active through empty StoreKit reads and empty web polls
jakemor Aug 16, 2026
606f7a7
Scope the anti-downgrade guard by device-read authority
jakemor Aug 16, 2026
0ae3358
Protect nil-store entitlements and stamp .appStore on SK1 entitlements
jakemor Aug 16, 2026
d53fef6
Merge remote-tracking branch 'origin/develop' into fix/subscription-s…
yusuftor Aug 19, 2026
81f3ea6
Hold the guard through entitlement-mapping failures
yusuftor Aug 19, 2026
6e70dcf
Stamp .appStore only on SK1 entitlements a transaction unlocks
yusuftor Aug 19, 2026
699a8d2
Reword changelog entries to match the scoped guard
yusuftor Aug 19, 2026
9d1ef98
Document the uncorrected isActive signal and the web revocation tradeoff
yusuftor Aug 19, 2026
287a399
Correct the revocation wording: empty responses are artifacts
yusuftor Aug 19, 2026
d1ca3fa
Restore the test scheme to develop's parallel default
yusuftor Aug 19, 2026
c1fe74e
Bump to 4.16.4 and ban Unreleased changelog headings
yusuftor Aug 19, 2026
47a5ba1
Update CHANGELOG.md
yusuftor Aug 19, 2026
3204994
Update CHANGELOG.md
yusuftor Aug 19, 2026
82ff1ee
Restore the App Store changelog entry with its precondition
yusuftor Aug 19, 2026
0f2cae7
Merge pull request #506 from superwall/fix/subscription-status-anti-d…
yusuftor Aug 19, 2026
93ede39
chore(github): require an affected-user link and setup details in bug…
yusuftor Aug 24, 2026
ebc7611
chore(github): warn against posting identifying user IDs in the affec…
yusuftor Aug 24, 2026
e1eeafe
chore(github): apply review suggestions to the bug report form
yusuftor Aug 24, 2026
6519c3c
feat: add dev mode for previewing local paywalls
chroxify Aug 24, 2026
411239d
Merge pull request #510 from superwall/chore/bug-report-issue-form
yusuftor Aug 24, 2026
b042bb7
fix(configure): stop the container escaping to the redeemer mid-init
yusuftor Aug 25, 2026
ead8520
review: kick off the cold-launch poll from Superwall's configure init
yusuftor Aug 25, 2026
15647e1
Merge pull request #512 from superwall/fix/dependency-container-init-…
yusuftor Aug 25, 2026
4f1779f
Merge remote-tracking branch 'origin/develop' into christo/sw-framewo…
yusuftor Aug 25, 2026
48b6b35
chore: fold dev mode changelog entry into staged 4.16.4 section
yusuftor Aug 25, 2026
5d8c076
chore: restage 4.16.4 release as 4.17.0
yusuftor Aug 25, 2026
154f0a2
review: gate dev links out of production and unfreeze the dev-mode cache
yusuftor Aug 25, 2026
75da4e8
review: pin dev-server mount URLs to the manifest's origin
yusuftor Aug 25, 2026
4a032b8
review: log when a dev server surface is rejected as off-origin
yusuftor Aug 25, 2026
d1f5e0d
chore(examples): scope Advanced app ATS to web content and local netw…
yusuftor Aug 26, 2026
254d6de
chore: split DevServerManifest.swift into one file per type
yusuftor Aug 26, 2026
3482bf2
style: invert the paywall picker's open guard into a positive early r…
yusuftor Aug 26, 2026
0d7ce5e
style: split the paywall picker gate into a three-branch predicate
yusuftor Aug 26, 2026
362950d
style: state the picker gate positively with guard
yusuftor Aug 26, 2026
11cd922
style: group the ATS warning flag with the locator's other state
yusuftor Aug 26, 2026
6fed06c
style: split the ATS warning gate into single-condition checks
yusuftor Aug 26, 2026
c22e098
style: split the dev link parse into single-condition guards
yusuftor Aug 26, 2026
cf2020c
docs: drop the superwall.lock binding detail from the dev mode change…
yusuftor Aug 26, 2026
e751849
review: drop the debugger's product-variables timeout
yusuftor Aug 26, 2026
6240aa2
style: positive-if and multiline-guard formatting in dev mode gates
yusuftor Aug 26, 2026
b61b66e
feat!: replace devMode and devServerURL with SuperwallOptions.devServer
yusuftor Aug 26, 2026
ae9e819
chore: retrigger CI after a stuck Pullfrog run
yusuftor Aug 26, 2026
d6f8f63
fix(debugger): make Preview work for unpushed dev-server surfaces
yusuftor Aug 26, 2026
ee963aa
feat(dev): serve matching local surfaces wholesale instead of patchin…
yusuftor Aug 26, 2026
75c29ba
feat(dev): mark locally served paywalls and honour their presentation…
yusuftor Aug 27, 2026
7e87a07
fix(events): dedupe subscription status changes by logical state
yusuftor Sep 1, 2026
a0a81c0
review: gate the cache save, document logical-change semantics, add b…
yusuftor Sep 1, 2026
29146b4
review: mirror logical-change docs onto the ObjC delegate
yusuftor Sep 1, 2026
5f22a4e
Merge pull request #515 from superwall/fix/subscription-status-logica…
yusuftor Sep 1, 2026
5210fac
feat(entitlements): add grantedEntitlements merged into subscription …
yusuftor Sep 1, 2026
84e9453
review: harden granted merge, resolution locking, and cached-status r…
yusuftor Sep 1, 2026
800b5c3
review: lock the status store itself, not just resolution
yusuftor Sep 1, 2026
9235459
review: snapshot granted once per resolution, add base-race regressio…
yusuftor Sep 1, 2026
de887fa
review: strengthen the base-race test's assertions
yusuftor Sep 1, 2026
430e284
refactor: make granted a first-class source in every customer info merge
yusuftor Sep 2, 2026
913ff2c
review: keep LogScope raw values stable, cover the external-controlle…
yusuftor Sep 2, 2026
730c9ba
refactor: move status publishing into its own file, rename resolved/u…
yusuftor Sep 2, 2026
9621c63
review: have publishSubscriptionStatus take its own lock, pass the gr…
yusuftor Sep 2, 2026
9697d8a
review: snapshot granted entitlements inside the publish lock
yusuftor Sep 2, 2026
6b95ed5
review: fix the 15 findings from the max-effort review
yusuftor Sep 2, 2026
8fcb871
review: rebuild external customer info from a consistent snapshot, st…
yusuftor Sep 2, 2026
7e6c817
review: bound the customer info retry, cover the external-controller …
yusuftor Sep 3, 2026
78eca5d
docs: plainer wording in the granted entitlement ids comment
yusuftor Sep 3, 2026
782ed3e
refactor: name what prompted a status publish instead of nil + a flag
yusuftor Sep 3, 2026
f7b54b4
chore: stop swiftlint crawling nested git worktrees
yusuftor Sep 3, 2026
a78034c
refactor: drop a stale customer info build instead of rebuilding it
yusuftor Sep 3, 2026
1949e21
fix: granted entitlements no longer decide an unknown subscription st…
yusuftor Sep 3, 2026
d620a7b
docs: say which thread subscribers run on instead of 'don't block'
yusuftor Sep 3, 2026
6b53761
docs: trim the changelog to what changed since the last release
yusuftor Sep 3, 2026
ad1da70
Merge pull request #516 from superwall/feat/sw-5794-granted-entitlements
yusuftor Sep 4, 2026
79e8ed2
Merge remote-tracking branch 'origin/develop' into christo/sw-framewo…
yusuftor Sep 4, 2026
7689d10
refactor(debugger): hold published paywalls as PaywallSummary
yusuftor Sep 4, 2026
eedda06
review: keep gating real, contain manifest decode failures, share the…
yusuftor Sep 4, 2026
5181d83
review: inherit dashboard-owned behaviour, keep the manifest identifi…
yusuftor Sep 4, 2026
8dee668
fix(dev): let the local paywall keep owning its notifications
yusuftor Sep 4, 2026
0027657
fix(dev): inherit what the manifest can't carry, honour multi-paywall…
yusuftor Sep 4, 2026
bff8c79
refactor(dev): read paywall settings from the published paywall only
yusuftor Sep 4, 2026
694331b
fix(dev): take identity from the paywall a surface stands in for
yusuftor Sep 4, 2026
a280567
docs(dev): stop promising config.ts presentation reaches dev mode
yusuftor Sep 4, 2026
e518f87
docs(dev): name local notifications as the exception to inheritance
yusuftor Sep 4, 2026
1af8f0a
docs(dev): make the on-device cache exception explicit
yusuftor Sep 4, 2026
8a29ef0
fix: send unknown entitlement details as null, not as missing
yusuftor Sep 7, 2026
1647e0e
test: cover the string-valued fields and tidy the filter helper
yusuftor Sep 7, 2026
9539a22
refactor: null the unknown fields only for audience filters
yusuftor Sep 7, 2026
f60d255
test: pin the one call site that turns the null encoding on
yusuftor Sep 7, 2026
193dc25
Update CHANGELOG.md
yusuftor Sep 7, 2026
1b24185
Merge pull request #517 from superwall/fix/entitlement-unknown-fields
yusuftor Sep 7, 2026
1e97fc2
feat(dev): present a local paywall the way its config.ts says
chroxify Sep 9, 2026
7ba938d
feat(dev): let config.ts pick intro offer eligibility
yusuftor Sep 10, 2026
a7e0db7
fix(dev): rebuild the paywall when config.ts settings change
yusuftor Sep 10, 2026
bfa0d23
docs(dev): name intro offer eligibility as config.ts's
yusuftor Sep 10, 2026
cb48599
Fix crash when register is called from more than one thread
yusuftor Sep 11, 2026
3dd3685
Serialize the task swap on a queue instead of a lock
yusuftor Sep 11, 2026
519c7cd
Hand operations to one task through a stream
yusuftor Sep 11, 2026
9ad7439
Address review: comment wording, last racy swap, test-only surface
yusuftor Sep 11, 2026
af2d496
Run operations at the enqueuer's priority, and restore Sendable
yusuftor Sep 11, 2026
4ffdb41
Guard the priority test, and correct a comment
yusuftor Sep 11, 2026
a414575
fix: refresh and sync integration device attributes
Makisuo Sep 13, 2026
29239d5
Skip the purchased-product fetch on StoreKit 2 at cold launch
yusuftor Sep 14, 2026
eb96e0d
Log failed purchased-product fetches and fix a stale doc comment
yusuftor Sep 14, 2026
86ebffd
Drop the load timing logs
yusuftor Sep 14, 2026
b1b7b53
Merge pull request #522 from superwall/fix/skip-purchased-product-fet…
yusuftor Sep 14, 2026
e7941b2
Publish config from the saved entitlements before the StoreKit read
yusuftor Sep 14, 2026
18875a3
Restore each saved item on its own expiry, and take the fast path wit…
yusuftor Sep 14, 2026
3953a56
Seed device purchases only, admit lifetime purchases, and pin the exp…
yusuftor Sep 14, 2026
4176c14
Test the fast path for a web-only subscriber
yusuftor Sep 14, 2026
0ac31c4
Take the fast path for developer-granted entitlements
yusuftor Sep 14, 2026
a5dac2f
Seed consumables inactive and scope the fast path to StoreKit 2
yusuftor Sep 14, 2026
9ece061
Say the early publish applies to StoreKit 2 in the changelog
yusuftor Sep 14, 2026
6ff9697
Update CHANGELOG.md
yusuftor Sep 15, 2026
1fab1de
Wait for the purchases load only where the answer depends on it
yusuftor Sep 15, 2026
7a92811
Carry grants into the restore, and don't restore an undated subscription
yusuftor Sep 15, 2026
5b16335
Merge grants in the caller, and match the read's merge rules
yusuftor Sep 15, 2026
991eebc
Address the review on the device-attribute refresh
yusuftor Sep 15, 2026
bfb8793
Restore the whole integration state after a reset
yusuftor Sep 15, 2026
965e848
Merge pull request #520 from superwall/fix/register-task-race
yusuftor Sep 15, 2026
03d47bd
Deactivate lapsed saved rows before merging grants in
yusuftor Sep 15, 2026
922b1d7
Keep only the install-scoped attributes across a reset
yusuftor Sep 15, 2026
82e160c
Keep the eligible-override intro check on post-read data
yusuftor Sep 15, 2026
b6cab4c
Close the two ways a person-scoped id could still survive a reset
yusuftor Sep 15, 2026
26dc72f
Derive the integration attribute cases from CaseIterable
yusuftor Sep 15, 2026
7b1741e
Drop the scope assertion the exhaustive switch already guarantees
yusuftor Sep 15, 2026
2124140
Wait for the read in the entitlement-history check too
yusuftor Sep 15, 2026
6eb2c24
Wait for the read in the custom-product trial check too
yusuftor Sep 16, 2026
3bb6ef4
Skip the purchases wait when no App Store product is involved
yusuftor Sep 16, 2026
f9c3590
Say what actually decides whether the load can move an entitlement
yusuftor Sep 16, 2026
153dba7
Only treat a grant as in reach for apps with a purchase controller
yusuftor Sep 16, 2026
8f067a7
Drop the granted short-circuit, which named the wrong refresh
yusuftor Sep 16, 2026
bfbfde2
Update CHANGELOG.md
yusuftor Sep 16, 2026
7ad336f
Merge pull request #523 from superwall/fix/publish-config-from-saved-…
yusuftor Sep 16, 2026
703e3ce
Merge develop into codex/appsflyer-device-context
yusuftor Sep 16, 2026
bf25d0d
Call them device identifiers, and repair them when an app overwrites …
yusuftor Sep 16, 2026
95e2eaf
Lock status reads, emit in store order, and publish corrected state d…
yusuftor Sep 16, 2026
1f44b3d
Judge an overwrite by the value, not just the key
yusuftor Sep 16, 2026
c9b7f32
Match the ATT status on what it says, not how it's boxed
yusuftor Sep 16, 2026
7deda32
Don't let a boolean pass for an ATT status
yusuftor Sep 16, 2026
c6fd4f3
Leave the saved customer info alone under an external purchase contro…
yusuftor Sep 16, 2026
84bd145
Merge pull request #521 from superwall/codex/appsflyer-device-context
yusuftor Sep 16, 2026
5209ccb
Pin the external-controller guard on the restore with a test
yusuftor Sep 16, 2026
c30012a
Merge remote-tracking branch 'origin/develop' into fix/subscription-s…
yusuftor Sep 16, 2026
fb5be35
Correct lapsed rows under a purchase controller without touching its …
yusuftor Sep 16, 2026
4a0e8ee
Leave the customer info alone under a purchase controller after all
yusuftor Sep 16, 2026
7738da3
Merge pull request #526 from superwall/fix/subscription-status-review…
yusuftor Sep 17, 2026
c29fdce
Stop identify() hanging after an install match, and answer paywall ov…
yusuftor Sep 17, 2026
d568e98
Assert only what other suites can't disturb in the user-switch test
yusuftor Sep 17, 2026
387c6a1
Drop the overwrite check on the paywall attribute path
yusuftor Sep 17, 2026
b56231b
Say on reset(duringIdentify:) which queue it runs on, and check the r…
yusuftor Sep 17, 2026
5647609
Merge pull request #527 from superwall/fix/identify-switch-hang
yusuftor Sep 17, 2026
0919782
Keep a paywall's experiment with the request that presented it
yusuftor Sep 17, 2026
d714e83
Drop the redundant claim log and fix the present operator's doc comment
yusuftor Sep 17, 2026
208e046
Keep a getPaywall claim made while the paywall is on screen, and don'…
yusuftor Sep 17, 2026
da4041f
Only restore a handed-out claim on an appearance that starts a presen…
yusuftor Sep 17, 2026
b1c7a81
Tie the stored publisher check to this test's own presentation
yusuftor Sep 17, 2026
5632083
Merge pull request #528 from superwall/fix/shared-paywall-attribution
yusuftor Sep 17, 2026
94fb59d
Update CHANGELOG.md
yusuftor Sep 17, 2026
059a2aa
Show the paywall version a claim resolved, not just its products
yusuftor Sep 17, 2026
f88573e
Install a claim's delegate before reloading, and load once on restore
yusuftor Sep 17, 2026
2e841b5
Update CHANGELOG.md
yusuftor Sep 18, 2026
7424c1f
Merge pull request #529 from superwall/fix/claim-brings-paywall-version
yusuftor Sep 18, 2026
8d3fe5c
Surface the web funnel's user attributes on a redeemed code
yusuftor Sep 17, 2026
5946a33
Keep the old Objective-C initialiser and document blank answers
yusuftor Sep 18, 2026
5d0d919
Pin the blank answer in the round trip test
yusuftor Sep 18, 2026
630dd61
Only send freeTrial_start to the paywall when a trial started
ianrumac Sep 18, 2026
6d04a83
Merge pull request #530 from superwall/feat/redemption-user-attributes
yusuftor Sep 18, 2026
a6b5c06
Keep the mock alive for the whole of the new message handler tests
yusuftor Sep 18, 2026
62f7f4f
Merge pull request #531 from superwall/ir/fix/gate-free-trial-start-m…
yusuftor Sep 18, 2026
e96b181
Merge remote-tracking branch 'origin/develop' into christo/sw-framewo…
yusuftor Sep 18, 2026
aecdd16
Update CHANGELOG.md
yusuftor Sep 18, 2026
aa55087
Merge pull request #511 from superwall/christo/sw-framework-support
yusuftor Sep 18, 2026
8ffa7e2
Update CHANGELOG.md
yusuftor Sep 18, 2026
2941322
Scope the dev server lookup to the address it was asked for
yusuftor Sep 18, 2026
c1ae976
Address review feedback on the dev server and shared paywall controller
yusuftor Sep 18, 2026
e7f2760
Hold the dev server lookup to the server it set out to find
yusuftor Sep 18, 2026
1a4c22e
Let the early publish test wait for the purchases load to start
yusuftor Sep 18, 2026
6e75fa7
Hold only the entitlements a device read has no authority over
yusuftor Sep 21, 2026
4f2139a
Refresh the dev server manifest before previewing or presenting a loc…
yusuftor Sep 21, 2026
dcc2e9e
Send configState from processConfig instead of from its callers
yusuftor Sep 21, 2026
d63ddd5
Keep entitlements a device read has no authority over, whether or not…
yusuftor Sep 21, 2026
d873648
Drop a selected dev surface the refreshed manifest no longer lists
yusuftor Sep 21, 2026
62e294a
Pin the intro offer eligibility key in the manifest fixture
yusuftor Sep 21, 2026
dbaebd5
Update changelog, remove redundant code
yusuftor Sep 21, 2026
0014fae
Drop an entitlement past its own expiry even when the device read sai…
yusuftor Sep 21, 2026
d4055e6
Resolve the debugger's selected surface the way Present does
yusuftor Sep 21, 2026
9835f8b
Say which stores the expiry prune actually settles
yusuftor Sep 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions .github/ISSUE_TEMPLATE/bug_report.md

This file was deleted.

131 changes: 131 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: 🐛 Bug report
description: Report a bug in SuperwallKit. The more you give us up front, the faster we can find the cause.
title: "[BUG] "
labels: ["bug"]
body:
- type: checkboxes
id: checklist
attributes:
label: New issue checklist
options:
- label: I have read the [documentation](https://superwall.com/docs) and this doesn't appear to be expected behavior
required: true
- label: I have searched [existing issues](https://github.com/superwall/Superwall-iOS/issues) and this is not a duplicate
required: true
- label: I have tried to reproduce the issue in a minimal sample project I can share
required: false
- type: input
id: affected-user
attributes:
label: Affected user
description: >
A link to a user who hit the bug lets us check their event logs, which is often the
fastest route to a diagnosis. In the
[dashboard](https://superwall.com/select-application?pathname=/applications/:app/users/v2),
open **Users**, search for the app user ID you pass to `Superwall.shared.identify(userId:)`
(or the `$SuperwallAlias:...` ID from `Superwall.shared.userId` if you don't identify users),
open the user, and paste the page URL. The link only opens for your own team and us,
but issues are public and the URL contains the user ID itself — so if your app user IDs
are personally identifying (e.g. an email address), paste the user's `$SuperwallAlias:...`
URL instead (shown on their user page), or share the link privately via the support chat
in the dashboard and mention this issue. If the bug isn't tied to a user (e.g. a build
error), write "N/A".
placeholder: https://superwall.com/applications/<appId>/users/v2/<userId>
validations:
required: true
- type: input
id: occurred-at
attributes:
label: When did it happen?
description: Approximate date and time the bug occurred, including timezone. Helps us correlate server-side logs.
placeholder: e.g. 2026-08-15 14:30 UTC
- type: input
id: sdk-version
attributes:
label: SuperwallKit version
placeholder: e.g. 4.16.3
validations:
required: true
- type: input
id: previous-sdk-version
attributes:
label: Last SDK version that worked
description: If the bug appeared after updating the SDK, which version were you on before?
placeholder: e.g. 4.15.4
- type: input
id: ios-version
attributes:
label: iOS version(s)
placeholder: e.g. iOS 26.5
validations:
required: true
- type: input
id: xcode-version
attributes:
label: Xcode version
placeholder: e.g. 26.1
validations:
required: true
- type: dropdown
id: installation
attributes:
label: Installation method
options:
- Swift Package Manager
- CocoaPods
- Other
validations:
required: true
- type: input
id: devices
attributes:
label: Devices/simulators affected
placeholder: e.g. iPhone 17 Pro, all simulators
- type: dropdown
id: repro-example
attributes:
label: Reproducible in the example app?
options:
- "Yes"
- "No"
- Haven't tried
validations:
required: true
- type: textarea
id: sdk-setup
attributes:
label: How is the SDK set up?
description: |
Briefly describe your integration — it changes which code paths run:
- Are you using a `PurchaseController` (e.g. with RevenueCat)? If so, where do you set `Superwall.shared.subscriptionStatus`?
- How do you present paywalls (`register(placement:)`, `PaywallView`, `getPaywall`)?
- Do you call `Superwall.shared.identify(userId:)`?
validations:
required: true
- type: textarea
id: description
attributes:
label: Describe the bug
description: A clear and concise description of the bug, including expected vs. actual behavior. Screenshots and screen recordings help a lot.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. ...
2. ...
validations:
required: true
- type: textarea
id: logs
attributes:
label: Debug logs
description: Set `options.logging.level = .debug` in `SuperwallOptions` before configuring the SDK, reproduce the bug, and paste the console output covering when it happened. Automatically formatted as code. Please redact anything personal — logs can contain user attributes you've set.
render: shell
- type: textarea
id: other
attributes:
label: Other information
description: Stack traces, crash reports, related issues, links, or anything else that gives context.
3 changes: 3 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ excluded:
- ${PWD}/Pods
- ${PWD}/DerivedData
- ${PWD}/.build
# Git worktrees live here, each holding a full copy of the SDK source, so
# linting them reports another branch's violations against this one.
- ${PWD}/.claude
- ${PWD}/Examples
- ${PWD}/Tests
- ${PWD}/Sources/SuperwallKit/StoreKit/Products/Receipt Manager/ASN1Swift
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

The changelog for `SuperwallKit`. Also see the [releases](https://github.com/superwall/Superwall-iOS/releases) on GitHub.

Comment thread
yusuftor marked this conversation as resolved.
## 4.17.0
### Enhancements
Comment thread
yusuftor marked this conversation as resolved.

- Adds `grantedEntitlements` so you can grant entitlements from your own backend, which the SDK merges with device and web entitlements.
- Adds `userAttributes` to the `RedemptionInfo` you get from `didRedeemLink`, so you can read the answers someone gave on your web paywall funnel after they redeem in your app.
Comment thread
yusuftor marked this conversation as resolved.
- Adds `SuperwallOptions.devServer` for development builds: with a `superwall dev` server running, paywalls render from your live, local paywall code while configuration, placements, audience evaluation and assignment stay real. Use `.default` on a simulator, which finds the dev server on localhost automatically; on a physical device use `.url(...)` with the Device URL `superwall dev` prints. The dev server also activates test mode, disables preloading, and skips the test mode intro sheet.

### Fixes

- Fixes trial reminders being scheduled for users who bought without getting the intro offer.
- Refreshes the IDFV, IDFA and tracking consent for integrations when the app becomes active or integration attributes are set again, and clears the IDFA when consent is revoked. These now also go into the user attributes `idfv`, `idfa` and `attStatus`, so server-side integrations such as AppsFlyer can read them. The SDK owns those three keys and will overwrite any value your app has set on them. `reset()` and identifying a different user now keep the integration attributes that describe the device, such as the AppsFlyer and Adjust IDs, and drop the ones that describe the person, such as the Amplitude and Customer.io user IDs.
- Fixes duplicate device attribute and subscription status change events being tracked when the subscription status is repeatedly set to the same logical state. As part of this, `subscriptionStatusDidChange` now fires only when the logical status changes — the status case, the set of entitlements, or an entitlement's `isActive` flag. Updates to transaction metadata such as expiry dates or renewal state no longer trigger it; use `customerInfoDidChange` for those.
- Fixes subscribers with an unexpired subscription being reported as `inactive` on cold launch when the App Store has no purchases to report. Refunded and expired App Store subscriptions still deactivate immediately.
- Fixes slow cold launches for subscribers on a weak network by no longer fetching their purchased products from StoreKit before the SDK is ready. Applies to StoreKit 2.
- Fixes a data race during SDK configuration that Thread Sanitizer flagged on every launch.
- Fixes a crash when `register` is called from more than one thread at a time.
- Fixes a hang when identifying a different user after an install attribution match had been found.
- Fixes issue where paying web users could end up having a temporary inactive subscription status if the server temporarily returns no entitlement data for them.
- Fixes audiences matching users they shouldn't when you use a Purchase Controller.
- Fixes paywall opens and purchases being reported under the wrong experiment when two campaigns share a paywall and a second placement fires while it is on screen.

## 4.16.3

### Fixes
Expand Down
16 changes: 16 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ When bumping the version, update all three files:
3. `CHANGELOG.md` (add new version entry at top)

- Follows semantic versioning
- **Never use an `## Unreleased` heading in `CHANGELOG.md`.** Unreleased changes always live under the next concrete version number (e.g. `## 4.16.4`).
- To pick that number, compare the version on `develop` with the version on `master`:
- If develop's version is **above** master's, a release is already staged — add your entries to that existing top section. Do not bump again.
- If develop's version **equals** master's, start the next release: add a new version section and bump all three files together (patch/minor/major per the change).

### Testing

Expand Down Expand Up @@ -110,3 +114,15 @@ When creating PRs, always include the checklist from `.github/PULL_REQUEST_TEMPL
- [ ] I have run `swiftlint` in the main directory and fixed any issues.
- [ ] I have updated the SDK documentation as well as the online docs.
- [ ] I have reviewed the [contributing guide](https://github.com/superwall-me/paywall-ios/tree/master/.github/CONTRIBUTING.md)

### Integration device identifiers

AttributionFetcher refreshes IDFV/IDFA/ATT when setting integration attributes and
on app activation after an integration has been configured. Compare the complete
refreshed snapshot, not just provider IDs. Sync device values into user attributes
(the server integration router reads those) only when that snapshot changes, since
every sync costs a `user_attributes` event; explicit nulls clear stale IDs after
ATT revocation. ATT is serialized as a numeric string in integration attributes.
`idfv`, `idfa` and `attStatus` are SDK-owned user-attribute keys — document any
change to that set in the changelog and the online docs. Don't gate the IDFA on
the ATT status: `identifierForAdvertisers` already filters the all-zero id.
2 changes: 1 addition & 1 deletion Examples/Advanced/Advanced/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>UIAppFonts</key>
Expand Down
5 changes: 5 additions & 0 deletions Examples/Basic/Basic/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
</array>
</dict>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>UIAppFonts</key>
<array>
<string>Rubik-Regular.ttf</string>
Expand Down
Loading
Loading