Release 2.15.1#707
Open
itmindbox wants to merge 26 commits into
Open
Conversation
Merge 'master' into 'develop' after release
…code (#692) * MOBILE-72: Refactor HTTP response handling to prioritize HTTP status code HTTP code is now the primary discriminator. Body status is only validated within the context of the HTTP code category. Fixes: 4xx + status "Success" no longer treated as success. * MOBILE-72: Add tests for HTTP response handling 12 test cases covering all key scenarios from the API spec: 2xx/4xx/5xx with various body statuses, needBaseResponse=false, emptyData=true, 404 special case, 3xx redirect handling. * MOBILE-72: Add comprehensive tests for HTTP response handling and default parameter for needBaseResponse --------- Co-authored-by: Vailence <utekeshev@mindbox.cloud>
Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.8.9 to 2.9.0. - [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md) - [Commits](sporkmonger/addressable@addressable-2.8.9...addressable-2.9.0) --- updated-dependencies: - dependency-name: addressable dependency-version: 2.9.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#702) Xcode 26.4 changed `xcrun simctl runtime list` output in a way that fastlane 2.232.2 mis-parses. scan crashes with `undefined method '[]' for nil` / `xcrun simctl runtime broken`, even though the simctl command returns valid JSON outside fastlane. Reproduced locally on the same Xcode that works for `xcodebuild test` directly. 2.233.0 includes the relevant fixes: - scan: Fix simulator selection when runtime build is missing from installed runtimes (#29894) - scan: Fix default_os_version when xcodebuild sdkVersion differs from simctl sdkVersion (#29977) Includes the auto-regenerated FastlaneSwiftRunner sources required by the new gem version.
Adds optional `operationsDomain` to `MBConfiguration` so projects served
via a CDP anonymizer can route operations and track-visit requests to
a separate host, avoiding personal-data leaks to `api.mindbox.ru`.
Affected routes (now resolve to `operationsDomain` when configured):
- `/v3/operations/{async,sync,async-custom}`
- `/v1.1/customer/mobile-track-visit`
- SDK logs upload
Config-fetch (`/mobile/byendpoint/*.json`) and `/geo` keep using `domain`.
Priority of resolution:
1. `settings.baseAddresses.operations` from the mobile JSON config
2. `operationsDomain` passed to `Mindbox.initialization(...)`
3. `nil` → fall back to `MBConfiguration.domain` (existing behavior)
The JSON-sourced value is persisted in `UserDefaults` so operations stay
pinned to the anonymizer across restarts. An explicit `null` / empty
value in a fresh config clears the cache (rollback channel); a
format-broken value preserves the previous good one.
Backwards compatibility:
- `operationsDomain` has a default value of `nil`
- `softReset()` preserves `operationsDomainFromConfig` (PD safety on
migration resets)
- Legacy `MBConfiguration` JSON without the new key decodes fine
Tests cover `URLRequestBuilder` host resolution, `MBConfiguration`
validation, `Settings` JSON decoding (incl. `null`/empty rollback),
`ConfigValidation` behavior, `MBNetworkFetcher` priority resolution,
`OperationsDomainConfigPolicy` decision matrix, persistence lifecycle,
and legacy-config decoding.
Follow-ups (separate commits):
- Drop dead `SDKLogsRoute`
- Rewrite `URLValidator` (hardcoded TLD list, `&` bug)
- Allow optional `https://` scheme in `domain` / `operationsDomain` inputs
Extends `SettingsConfigParsingTests` with `baseAddresses` cases from the Pkl error stubs (`Error`, `TypeError`, `OperationsError`, `OperationsTypeError`) and a positive assertion in `test_SettingsConfig_shouldParseSuccessfully`. Updates JSON fixtures under `SettingsJsonStubs/` to carry the new `baseAddresses` block (sourced from `pkl-mobile-config`); adds `BaseAddressesError/` with four fixtures and wires them into the test bundle via `Mindbox.xcodeproj/project.pbxproj`. Switches `Settings.BaseAddresses` to a custom `init(from:)` with per-field `try?` so a type error on `operations` nils only that field — matching `FeatureToggles`/`SlidingExpiration`/`InAppSettings`. Drops two parsing tests from `OperationsURLRoutingTests` whose coverage is now duplicated (positive parse, missing `baseAddresses`). Rollback-channel cases (`null` and empty string) stay there — they exercise feature behavior, not schema parsing.
Adds `MindboxTests/Configuration/MBConfigurationTests.swift` (Swift
Testing, `.mbConfiguration` tag) — a single suite covering the full
behavior of `MBConfiguration`: programmatic init validation
(`domain`, `endpoint`, `operationsDomain`, UUID handling for
`previousInstallationId`/`previousDeviceUUID`), defaults, plist init,
Codable (legacy / new / decoder validation), and
`ConfigValidation.compare` across the whole input space (identity,
`nil` handling, `.rest`-affecting fields, `.shouldCreateCustomer`
priority, fields that must not trigger any change).
Consolidates from two sources:
- Plist init coverage from `MBConfigurationTestCase.swift` (XCTest,
deleted) — folded into a single parametrised section.
- Seven `MBConfiguration`-shaped tests previously living in
`OperationsURLRoutingTests.swift` (init validation, two
`ConfigValidation.compare` cases, legacy JSON decoding).
Adds `Tag.mbConfiguration` and registers the new file under a new
`Configuration/` group in `Mindbox.xcodeproj/project.pbxproj`.
`SDKLogsRoute` had no references in production code: SDK logs flow through `SDKLogsManager.sendLogs` → `EventRepository.send` → `EventRoute.asyncEvent` (`MBEventRepository.makeRoute` for `.sdkLogs`). Removes the type from `SDKLogsRequest.swift`. `SDKLogsRequest` (the Codable body) stays — it is the request payload encoded into `Event.body`. Updates `OperationsURLRoutingTests` to assert routing for `.sdkLogs` through the actual `EventRoute.asyncEvent` path. The dedicated `sdkLogsRouteUsesOperationsDomain` test is removed (subsumed by the extended `eventRoutesUseOperationsDomain` and `noOperationsDomainFallsBackToDomain` cases).
`MBConfiguration.domain` and `MBConfiguration.operationsDomain` now
accept `host`, `https://host`, and `http://host` (with or without
trailing slash). When a scheme is present in the input, requests are
built with that scheme; otherwise `https://` is used as before.
Mirrors the Android SDK's `SdkValidation.extractHost` / `toBaseUrl`
pair, so both platforms accept the same inputs (e.g. a value pasted
straight from the dashboard URL).
Adds `Mindbox/Network/Helpers/HostNormalizer.swift`:
- `extractHost` — strips scheme (case-insensitive), whitespace, and
trailing slashes.
- `toBaseURLString` — preserves an existing scheme or prepends
`https://`.
- `isValidHost` — runs the extracted host through `URLValidator`.
Encapsulates the awkward `URL(string: "https://" + host)` +
`URLValidator` pattern previously duplicated across three call
sites.
`URLRequestBuilder` builds the base URL via
`HostNormalizer.toBaseURLString(...)` before adding `path` / `queryItems`,
so the resolved scheme propagates to every route. Same value also
flows through `OperationsDomainConfigPolicy` when validating the
operations host coming from the JSON config.
Tests:
- `HostNormalizerTests` (Swift Testing) — extract / base-URL /
validation across scheme, case, trailing slash, whitespace.
- `MBConfigurationTests` — accepts `domain` / `operationsDomain`
with `https://`, `http://`, trailing slash. Replaces the previous
"scheme throws" invariant.
- `OperationsURLRoutingTests` — bare host → https default,
`https://` / `http://` preserved end-to-end, trailing slash
stripped before path append.
Backwards compatible: integrators who pass a bare host get exactly
the same URLs as before.
Replaces the old full-URL regex (hardcoded TLD list missing
`.app`/`.dev`/`.io`, `&` HTML-escape bug, per-call regex compile
via `try!`) with an RFC 1123-style host validator. New TLDs are
accepted automatically by structure — analogous to Android's
`PatternsCompat.DOMAIN_NAME`.
API: `URLValidator.isValidHost(_ host: String) -> Bool` (static, no
instance). Drops the previous `URLValidator(url:).evaluate()` shape;
callers (`MBConfiguration`, `OperationsDomainConfigPolicy`) are
updated.
Implementation is plain Swift (no regex, no `try!`):
- Each label: 1..63 chars, alnum + hyphen, hyphen not at edges.
- Hosts joined by `.`; single-label (`localhost`) and IPv4 literals
accepted (digits-only labels are valid alnum).
- Total length capped at 253 (RFC 1035), constants explicit.
- ASCII-only contract: punycode (`xn--…`) passes, Unicode literals
don't (callers must convert IDN to ACE).
Removes the thin `HostNormalizer.isValidHost` wrapper — it was a
trivial composition of `extractHost` + validation that didn't belong
in a normalizer. Call sites now spell out the chain explicitly:
`URLValidator.isValidHost(HostNormalizer.extractHost(value))`.
Tests:
- New `URLValidatorTests` (Swift Testing) with 22 cases covering
passing inputs (modern TLDs, localhost, IPv4, hyphenated and
single-char labels, mixed case, punycode, max label/host
length boundaries) and failing inputs (empty, whitespace,
underscore, edge-hyphen, empty labels, embedded scheme,
path/query, special characters, Unicode literals, length
overflow).
- Removed `testURLValidator` from `ValidatorsTestCase` — the
full-URL contract no longer applies.
- Removed redundant `isValidHost` tests from `HostNormalizerTests`
(covered by `URLValidatorTests` now).
…clusion Extract `applyDownloadedConfig(_:rawData:)` and `sendMonitoringLogsIfNeeded(_:)` so the .data branch reads as decode → assign → apply. Group the three `SessionTemporaryStorage` writes inside `setupSettingsFromConfig` into `applySessionStorageSettings(_:)` so the dispatcher reads as four steps. Move the rationale for excluding `operationsDomainFromConfig` from `softReset()` to the property's docstring, where it belongs.
The new parameter now sits right after `domain` instead of at the end — they're conceptually paired (main host vs its anonymizer override). Source-compatible: callers that don't pass `operationsDomain` are unaffected; the few that do (tests, ios-app) already listed it adjacent to `domain` and only need a follow-up reorder of their own.
…me://host form Backend may send `http://` for some anonymizer setups; previous logic stored the raw string verbatim, so trailing slashes / scheme-vs-host mismatches caused spurious re-saves. Normalize via HostNormalizer.toBaseURLString on save: scheme preserved (http/https), trailing slash stripped, missing scheme defaults to https. Idempotent — first config fetch after upgrade rewrites legacy values once, then `.keep` stably. Adapts existing Policy tests to the canonical form and adds coverage for the trailing-slash case from JSON config, http preservation, canonical-equality keep, and the legacy-value upgrade path.
… and routing tests Routing tests had three scheme/slash cases for `domain` (bare host, https preserved, http preserved, trailing-slash stripped) but only `https://` for `operationsDomain`. Same asymmetry in MBConfiguration init tests. Add the missing http/trailing-slash cases for `operationsDomain` in both, plus an end-to-end check that the canonical `scheme://host` form written by OperationsDomainConfigPolicy routes correctly through URLRequestBuilder.
…ject path - MBConfiguration decoder: drop the `try?` on `decodeIfPresent` so the result is `String?` not `String??`. Type errors propagate, matching how `endpoint`, `domain`, and the bool fields are decoded. - OperationsDomainConfigPolicy: split `.keep` into `.keep` and `.rejected(String)`. Previously `.keep` collapsed both "already in canonical form" and "invalid format — fall back". After the canonicalization fix this caused spurious "Invalid domain" error logs whenever a legacy raw value (e.g. `x.ru`) matched a stored canonical form (`https://x.ru`). - InAppConfigurationManager: handle the new `.rejected` case explicitly, drop the brittle `current != raw` condition that motivated the bug. - Regression test covers the legacy-vs-canonical match no longer being mis-logged as rejected.
…uild safety - URLValidator: enforce IPv4 octet ranges (0..255) for four-pure-digit-label inputs, matching Android's PatternsCompat.DOMAIN_NAME. `999.999.999.999` and `256.0.0.0` are now rejected; structural hostname rules unchanged. - URLRequestBuilder: stop silently falling back to an empty URLComponents when `URLComponents(string:)` fails — that produced relative URLs that passed the existing `components.url != nil` guard and hit the network with a bogus target. Throw `URLError.badURL` at the source. - Tests cover IPv4 overflow rejection, hostname pass-through for non-IPv4 numeric counts (3 / 5 labels), and the new fail-fast path.
`JSONSerialization.data(withJSONObject:options:)` was using `.prettyPrinted` for the trackVisit request body — wasted whitespace and indentation on every mobile-track-visit call. Server parses both forms identically; the change just trims a few dozen bytes per request and matches the codebase convention for network-path serialization. Default `options` value (`[]`) is fine, so the parameter is dropped entirely.
…lizer Replace `value.lowercased().hasPrefix(...)` with `value.range(of:options:[.caseInsensitive, .anchored])` so the scheme check no longer allocates a lowercased copy of the input on every call. Identical behaviour, cleaner intent (prefix-with-options vs. transform-then-check), and the prefix literals are pulled out as `static let` so `dropFirst(...)` no longer carries hard-coded length math. Adds a tiny `hasSchemePrefix` helper for `toBaseURLString` to avoid duplicating both range checks inline.
Mobile-130: Add operationsDomain
…Manager (#700) * MOBILE-120: Limit errorDetails to 1000 characters in InappShowFailureManager * MOBILE-120: Truncate errorDetails by UTF-8 byte limit and log truncation * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Vailence <utekeshev@mindbox.cloud> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
MOBILE-180: Trim `operationsDomain` config value before blank check
* MOBILE-164-Sync-send-error-raw * MOBILE-164: Add tests for raw sync-operation pass-through Cover MBNetworkFetcher.requestRaw, MBEventRepository.sendRaw, and the WebView sync-operation response shaping. Extract a pure helper TransparentView.makeSyncOperationResponse so the JS-bridge contract is unit-testable without spinning up WKWebView. * MOBILE-164: Address review feedback - MBNetworkFetcher.requestRaw: capture self strongly so completion is always invoked even if the fetcher were deallocated mid-request (matches the existing `request<T>` pattern). - TransparentView.handleSyncOperation: build the outgoing BridgeMessage first, then log based on its `type` so the non-UTF-8 fallback path reports "failed" instead of "success". --------- Co-authored-by: Vailence <utekeshev@mindbox.cloud>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updates the release version to 2.15.1. Automated PR: merge release/2.15.1 into master