Foundation for iOS client support#4
Merged
Merged
Conversation
Generate Kotlin→Swift golden vectors and convert the protocol module to KMP. - Add GoldenVectorsTest (protocol-crypto) to emit JSON golden vectors for the iOS XCTest suite and validate on the JVM. - Convert :protocol to Kotlin Multiplatform (jvm + iOS targets), produce an XCFramework, and reorganize sourceSets (commonMain + jvmTest) with serialization/cbor deps. - Enable kotlin.multiplatform plugin in root build and libs.versions.toml; add kotlinx.serialization to protocol-crypto tests. - Add BrokerClient.resetVerificationBackoff() and call it from SettingsScreen refresh action for diagnostics. - Minor import fix in Identifiers.kt.
Pass the envelope message type through push payloads so transports (APNs) can choose alert vs background delivery. Broker.buildPushData now accepts a MessageType and adds an "mtyp" field to the push map; call sites were updated to pass envelope.typ. ApnsPushTransport reads mtyp to decide apns-push-type and apns-priority (alert/10 for NOTIFICATION, background/5 otherwise) and builds an appropriate APS payload (mutable-content alert placeholder vs content-available). A unit test was added to verify NOTIFICATION uses alert push type and priority.
APNs push transport now supports separate provider-token signers for production and sandbox, with sandbox config falling back to the primary key for unscoped keys. Server config adds dedicated sandbox key ID/path env vars, and transport initialization now enables APNs when at least one environment is configured. Token invalidation on APNs 403 was tightened to only re-mint for remintable reasons (ExpiredProviderToken, MissingProviderToken), avoiding repeated re-mints on InvalidProviderToken misconfiguration that can trigger APNs 429s. Tests were updated for the new provider map API and add coverage to ensure InvalidProviderToken does not invalidate cached tokens.
Bump version to 1.3.1-rc.1 and add manifest query for net.extrawdw.notifly. Add launcher icon asset and wire GraphicsPipeline into AppGraph so captured notifications include app icons. Introduce IosBundleIdExclusions to keep NotiSync bundle IDs discoverable but never enable them; update registry logic and add unit tests. iOS screen: generic iOS icon, new masked icon shape, square icon rendering, and disable toggles for excluded bundles.
Use the operational key for relay message fetches, then retry once with the identity root on 401 when the broker has not yet ingested the current epoch. Also bumps the app version to 1.3.1-rc.2 and updates broker App Check allow-listing for the iOS app ID.
There was a problem hiding this comment.
Pull request overview
This PR lays the groundwork for iOS client support by moving the shared protocol module to Kotlin Multiplatform (with an iOS XCFramework), adding cross-platform crypto “golden vectors” for Swift compatibility testing, and updating server/APNs delivery and Android bridge UI behaviors needed for iOS.
Changes:
- Convert
:protocolto Kotlin Multiplatform and add an iOSNotiSyncProtocolXCFramework target while keeping JVM usage intact. - Improve APNs delivery semantics (env-scoped signing keys, message-type-aware alert vs background behavior, and safer token invalidation behavior).
- Add Kotlin-generated golden vectors (to be consumed by iOS XCTest) and refine Android-side iOS bridge UX (icons, exclusions, relay fetch retry behavior, diagnostics).
Reviewed changes
Copilot reviewed 22 out of 25 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| server/src/test/kotlin/net/extrawdw/notisync/server/ApnsPushTransportTest.kt | Updates APNs transport tests for env-scoped providers and new alert notification behavior. |
| server/src/main/kotlin/net/extrawdw/notisync/server/delivery/push/Apns.kt | Adds env-scoped APNs token providers, alert vs background branching, and remint rules. |
| server/src/main/kotlin/net/extrawdw/notisync/server/Config.kt | Adds sandbox APNs key/path config fields. |
| server/src/main/kotlin/net/extrawdw/notisync/server/broker/Broker.kt | Includes message type (mtyp) in push data for APNs delivery branching. |
| protocol/src/main/kotlin/net/extrawdw/notisync/protocol/Identifiers.kt | Adds JvmInline import for value classes under KMP. |
| protocol/build.gradle.kts | Converts :protocol to Kotlin Multiplatform and defines iOS XCFramework build. |
| protocol-crypto/src/test/kotlin/net/extrawdw/notisync/protocol/crypto/GoldenVectorsTest.kt | Adds JVM test that emits Swift-consumable golden vectors JSON. |
| protocol-crypto/build.gradle.kts | Enables Kotlin serialization plugin for test-only @Serializable vector schema. |
| gradle/libs.versions.toml | Adds Kotlin Multiplatform plugin alias. |
| deploy/notisync-broker-v2.service | Expands App Check allow-list to include iOS app ID. |
| build.gradle.kts | Adds Kotlin Multiplatform plugin to root plugin management. |
| app/src/test/java/net/extrawdw/apps/notisync/appicon/ShippedIconsTest.kt | Tests generic iOS icon fallback behavior without suppressing App Store fetches. |
| app/src/test/java/net/extrawdw/apps/notisync/ancs/IosAppRegistryTest.kt | Adds tests for excluded bundle IDs and enabled filtering. |
| app/src/main/java/net/extrawdw/apps/notisync/ui/SettingsScreen.kt | Adds a UI refresh action to reset verification backoff. |
| app/src/main/java/net/extrawdw/apps/notisync/ui/IosScreen.kt | Improves iOS bridge UI (icon masking, toggle exclusions, square icon rendering). |
| app/src/main/java/net/extrawdw/apps/notisync/transport/BrokerClient.kt | Retries relay fetch with identity root after operational-key 401. |
| app/src/main/java/net/extrawdw/apps/notisync/notification/GraphicsPipeline.kt | Refactors app icon attachment into a reusable suspend function. |
| app/src/main/java/net/extrawdw/apps/notisync/appicon/ShippedIcons.kt | Adds a separate generic iOS fallback icon API. |
| app/src/main/java/net/extrawdw/apps/notisync/appicon/IconResolver.kt | Adds optional inclusion of generic iOS fallback to avoid suppressing App Store fetch. |
| app/src/main/java/net/extrawdw/apps/notisync/AppGraph.kt | Attaches app icon for test notifications before mirroring. |
| app/src/main/java/net/extrawdw/apps/notisync/ancs/IosAppRegistry.kt | Prevents enabling excluded bundle IDs and persists iOS app discovery/enabled set. |
| app/src/main/AndroidManifest.xml | Adds Notifly to package visibility queries for diagnostic source. |
| app/build.gradle.kts | Bumps app version to 1.3.1-rc.2. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+162
to
+168
| // Sandbox (api.sandbox.push.apple.com) — its own env-scoped key, else reuse the (unscoped) one. | ||
| val sandboxKeyId = config.apnsKeyIdSandbox.ifBlank { config.apnsKeyId } | ||
| val sandboxPath = config.apnsPrivateKeyPathSandbox.ifBlank { config.apnsPrivateKeyPath } | ||
| if (sandboxKeyId.isNotBlank() && sandboxPath.isNotBlank()) { | ||
| val key = Es256.loadEcPrivateKeyPem(File(sandboxPath).readText()) | ||
| providers[RouteEnvironment.DEVELOPMENT] = ApnsJwtProvider(config.apnsTeamId, sandboxKeyId, key) | ||
| } |
Comment on lines
+87
to
+91
| _enabled.update { | ||
| if (IosBundleIdExclusions.isExcluded(bundleId)) { | ||
| it - bundleId | ||
| } else if (enabled) { | ||
| it + bundleId |
| * Phase 0 of the iOS plan: generate the Kotlin→Swift golden vectors and assert their self-consistency | ||
| * on the JVM so this doubles as a regression guard. The emitted JSON file is consumed by the iOS | ||
| * XCTest suite (Phases 2–3) to prove the native Swift crypto is byte-compatible with this reference | ||
| * implementation. See ~/.claude/plans/read-docs-notisync-ios-library-implement-giggly-sky.md §B.5 / §E. |
| val hpkeSealToRaw: HpkeRawVec, | ||
| val envelopeOpen: EnvelopeOpenVec, | ||
| ) { | ||
| fun vectorCount() = 10 |
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.
Summary
:protocolto Kotlin Multiplatform and add an iOSNotiSyncProtocolXCFramework target while keeping JVM consumers/tests intact.