Skip to content

refactor: move request signing to Swift - #872

Merged
nickolas-dimitrakas merged 1 commit into
workstation/swift-migrationfrom
refactor/request-signing-to-swift
Sep 1, 2026
Merged

nickolas-dimitrakas merged 1 commit into
workstation/swift-migrationfrom
refactor/request-signing-to-swift

Conversation

@nickolas-dimitrakas

@nickolas-dimitrakas nickolas-dimitrakas commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

The stack

  1. refactor: move request signing to Swift #872 — request signing
  2. refactor: move URL request header assembly to Swift #873 — URL request headers
  3. refactor: move endpoint host resolution to Swift #874 — endpoint host resolution
  4. test: pin the exact endpoint URL strings before converting them #875 — endpoint URL characterization tests
  5. refactor: move endpoint path-style decisions to Swift #876 — endpoint path-style decisions

Review bottom-up; merge top-down. This is #872.


First of five. Stacked on #868base it on #868's head after that PR is rebased onto
workstation/swift-migration
; it currently branches off #861 and is missing #862.

What moves

MPRequestSigner owns four things extracted from MPURLRequestBuilder:

  • the HMAC-SHA256 hex encode,
  • the METHOD\nDATE\npath[?query] signature shape (config, audience),
  • the METHOD\nDATE\npath<body> shape (identity, events),
  • and the 8192-character query cap.

hmacSha256Encode:key: keeps its selector as a one-line forward.
MPURLRequestBuilderTests.m calls it through a test-only category and remains the
behaviour contract.

Two ObjC quirks preserved on purpose

  1. An embedded NUL truncates. The original ran both strings through
    cStringUsingEncoding: + strlen, so anything after a NUL was never hashed. Swift
    reproduces that by hashing only the bytes before the first NUL — bytesUpToFirstNUL.
  2. A nil message or key yields nil, but an empty message still hashes.
    testInvalidHMACSha256Encode pins both halves.

The query cap counts UTF-16 units to match NSString.length, not Swift's grapheme count.

CommonCrypto → CryptoKit

Both are system libraries, so no podspec or Package.swift change. Output is
byte-identical, verified against the existing ObjC reference vector plus a new
openssl-derived one in the Swift mirror test.

Gate

Item Result
1. Zero public-ABI diff pass — abi-guard.sh check clean, Include/ diff empty
2. pod lib lint x3 podspecs iOS pass ("passed validation"); tvOS not runnable locally
3. Build iOS + tvOS iOS pass, no new warnings; tvOS not runnable locally
4. trunk check pass — no new issues
5. ObjC + Swift suites pass — ObjC 982/982, Swift 368/368 (14 new here)

MPURLRequestBuilder is not in mParticle-Apple-SDK/Include/, so it has no ABI baseline
entry.

tvOS is CI-only: this machine has the tvOS 26.2 SDK but only the 26.0 simulator
runtime, so no tvOS destination resolves and pod lint's tvOS leg fails the whole lint even
though iOS passes. Environmental, not a compile failure.

On the test suites: both suites flake under Xcode's default parallel testing on this
machine — MPUserDefaultsTests races on shared UserDefaults, and several slow ObjC
tests time out and force an xctest restart that prints "0 failures" while silently
skipping ~75 tests. Both reproduce on the unmodified base, so the counts above were taken
with -parallel-testing-enabled NO. Filed separately.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

🐦 Swift Migration Progress

Production implementation code at 0e50c4ced1ea compared with 502ba6d79e3e.

Area Goal Progress Base This PR Swift SLOC Objective-C remaining Change
Core SDK Short term — in scope ████▎░░░░░ 41.60% 41.90% 6,072 8,418 🚀 +0.30 pp
Core SDK Long term — all Objective-C ███░░░░░░░ 29.62% 29.85% 6,072 14,273 🚀 +0.23 pp
SDK kit infrastructure Short term — in scope ░░░░░░░░░░ 0.00% 0.00% 0 3,340 ➖ 0.00 pp
SDK kit infrastructure Long term — all Objective-C ░░░░░░░░░░ 0.00% 0.00% 0 3,725 ➖ 0.00 pp
Standalone kits Short term — in scope ▏░░░░░░░░░ 1.06% 1.06% 152 14,231 ➖ 0.00 pp
Standalone kits Long term — all Objective-C ▏░░░░░░░░░ 1.06% 1.06% 152 14,231 ➖ 0.00 pp

Objective-C retained by design: Core SDK 5,855 · SDK kit infrastructure 385 · Standalone kits 0.

This PR's code movement

Area Swift lines added Objective-C lines removed
Core SDK 58 64
SDK kit infrastructure 0 0
Standalone kits 0 0
How this is measured
  • Current composition uses production source lines of code (SLOC) from cloc; comments and blank lines are excluded.
  • Short term — in scope excludes the Objective-C the migration will not delete, so 100% is the end of this project: every in-scope implementation gone.
  • Long term — all Objective-C keeps the full denominator. Reaching 100% there means the public API itself becomes Swift, which is a breaking change reserved for a future major release.
  • The gap between the two rows is the retained public/kit contract, runtime-identity, and boundary-glue surface listed in Tools/swift-migration-retained-objc.txt.
  • Retained wrappers keep their Objective-C interface but still shed logic to Swift. That thinning moves the long-term row and the retained figure, not the short-term row.
  • Both revisions are measured with the manifest from the head revision, so a manifest edit does not by itself move the reported change. A retained file this pull request renamed or deleted still counts as retained at the base.
  • Pull request movement uses physical additions/deletions from git diff base...head --numstat; it counts retained files too and is intentionally separate from SLOC totals.
  • Core excludes SDK kit infrastructure and vendored libraries. Standalone kits include only files below Kits/**/Sources.
  • Tests, examples, headers, build outputs, vendored libraries, and the MParticle/Sources Swift overlay are excluded.
  • Objective-C++ (.mm) is included in the Objective-C figures and removed counts.

Generated with cloc 2.10. This report is informational and does not gate migration direction.

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

📦 SDK Size Impact Report

Measures how much the SDK adds to an app's size (with-SDK minus without-SDK).

Metric Target Branch This PR Change
App Bundle Impact 2.16 MB 2.16 MB +4 KB
Executable Impact 848 bytes 848 bytes +N/A
XCFramework Size 6.66 MB 6.67 MB +4 KB

➡️ SDK size impact change is minimal.

Raw measurements

Target branch (workstation/swift-migration):

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":2292,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":2208,"sdk_executable_impact_bytes":848,"xcframework_size_kb":6824}

This PR:

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":2296,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":2212,"sdk_executable_impact_bytes":848,"xcframework_size_kb":6828}

Base automatically changed from feat/BWS-Swift-Migration-9 to workstation/swift-migration August 31, 2026 18:01
@nickolas-dimitrakas
nickolas-dimitrakas force-pushed the refactor/request-signing-to-swift branch from 1832cb7 to 4ebab21 Compare August 31, 2026 20:37
@nickolas-dimitrakas
nickolas-dimitrakas marked this pull request as ready for review September 1, 2026 14:17
@nickolas-dimitrakas
nickolas-dimitrakas requested a review from a team as a code owner September 1, 2026 14:17
@cursor

cursor Bot commented Sep 1, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes how x-mp-signature is computed for config, audience, identity, and events; parity tests mitigate risk but any subtle crypto or string-format drift would break authenticated API calls.

Overview
Extracts HTTP request signing from MPURLRequestBuilder into a new ObjC-exposed Swift type, MPRequestSigner, as the first step in the network Swift migration.

MPURLRequestBuilder no longer uses CommonCrypto inline for HMAC or hand-built signature strings. It imports the Swift module and delegates HMAC-SHA256 hex, canonical signature message formatting (METHOD\nDATE\npath[?query] vs METHOD\nDATE\npath<body>), and the 8192 UTF-16-unit query limit to MPRequestSigner. The private hmacSha256Encode:key: wrapper remains a one-line forward.

MPRequestSigner implements HMAC with CryptoKit and deliberately preserves legacy ObjC behavior: nil message or key → nil HMAC, embedded NUL truncates inputs before hashing, and empty query still uses ?. New MPRequestSignerTests lock these rules plus a reference HMAC vector; existing MPURLRequestBuilderTests stay the integration contract.

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

Extracts HMAC-SHA256 encoding and signature-message assembly from
MPURLRequestBuilder into a Foundation-only Swift type, per
docs/swift-migration/CONVERSION-RECIPE.md.

MPRequestSigner owns four things: the HMAC hex encode, the two
signature-message shapes (path + "?" + query for config and audience,
path + body for identity and events), and the 8192-character query cap.
The .m still owns NSMutableURLRequest, the cache policy, the timeout,
every header assignment, and its MPILogError calls -- it resolves the
state machine, kit container, web view and user defaults into plain
values before calling Swift, because mParticle-Apple-SDK-Swift cannot
import the ObjC module.

hmacSha256Encode:key: keeps its selector as a one-line forward.
MPURLRequestBuilderTests.m calls it through a test-only category, and it
stays the behaviour contract.

Two ObjC behaviours are preserved deliberately and covered by tests:

- The original passed the strings through cStringUsingEncoding: and
  strlen, so an embedded NUL truncates the message or the key. Swift
  reproduces that by hashing only the bytes before the first NUL.
- A nil message or key yields nil, but an empty message still hashes.
  MPURLRequestBuilderTests testInvalidHMACSha256Encode pins both.

The query cap counts UTF-16 units, matching NSString.length rather than
Swift's grapheme count.

Signing switches from CommonCrypto to CryptoKit. Both are system
libraries, so no podspec or Package.swift change is needed, and the
output is byte-identical -- verified against the existing ObjC reference
vector plus a new openssl-derived one in the Swift mirror test.

MPURLRequestBuilder is not in mParticle-Apple-SDK/Include/, so it has no
ABI baseline entry; Include/ has a zero diff and abi-guard.sh check
passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nickolas-dimitrakas
nickolas-dimitrakas force-pushed the refactor/request-signing-to-swift branch from 4ebab21 to 0e50c4c Compare September 1, 2026 15:00
@nickolas-dimitrakas
nickolas-dimitrakas merged commit 95f8700 into workstation/swift-migration Sep 1, 2026
79 of 80 checks passed
@nickolas-dimitrakas
nickolas-dimitrakas deleted the refactor/request-signing-to-swift branch September 1, 2026 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants