mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
Audit KMP artifact readiness for MiniPay integration (#1838)
* update specs * update specs * pr feedback
This commit is contained in:
@@ -78,15 +78,17 @@
|
||||
|
||||
## Backlog
|
||||
|
||||
| ID | Title | Status | Priority | Depends On | Plan | PR |
|
||||
| ----- | ------------------------------------------------------------- | -------- | -------- | ---------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| NS-01 | Physical-device validation matrix for Android + iOS NFC flows | Done | High | - | [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | - |
|
||||
| NS-02 | iOS Camera MRZ Phase 2 | Deferred | Medium | NS-01 | - | - |
|
||||
| NS-03 | Publishing readiness for AAR + XCFramework artifacts | Ready | High | NS-01 | [plans/NS-03-publishing-readiness.md](./plans/NS-03-publishing-readiness.md) | - |
|
||||
| NS-04 | APDU allowlist in KMP NFC bridge handler | Ready | High | - | [plans/NS-04-apdu-allowlist.md](./plans/NS-04-apdu-allowlist.md) | - |
|
||||
| NS-05 | LifecycleBridgeHandler type/error semantics on iOS | Ready | Low | - | [plans/NS-05-lifecycle-handler-semantics.md](./plans/NS-05-lifecycle-handler-semantics.md) | - |
|
||||
| NS-06 | Align KMP callback/result contract with canonical SDK types | Done | Medium | NS-01 | [plans/NS-06-kmp-callback-contract-alignment.md](./plans/NS-06-kmp-callback-contract-alignment.md) | - |
|
||||
| NS-07 | Remove legacy `{ type }` shim from native lifecycle handlers | Blocked | Medium | - | - | Blocked on WebView bundle emitting canonical outcomes instead of flat `{ type }` payloads. Requires coordinated change: update `ConfirmIdentificationScreen.tsx` and `ProvingScreen.tsx` to send canonical `VerificationResult`, then remove the `type != null` branch from both Android and iOS `LifecycleBridgeHandler`. |
|
||||
| ID | Title | Status | Priority | Depends On | Plan | PR |
|
||||
| ----- | ------------------------------------------------------------- | -------- | -------- | ------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| NS-01 | Physical-device validation matrix for Android + iOS NFC flows | Done | High | - | [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | - |
|
||||
| NS-02 | iOS Camera MRZ Phase 2 | Deferred | Medium | NS-01 | - | - |
|
||||
| NS-03 | Publishing readiness for AAR + XCFramework artifacts | Done | High | NS-01 | [plans/NS-03-publishing-readiness.md](./plans/NS-03-publishing-readiness.md) | N/A (audit-only) |
|
||||
| NS-04 | APDU allowlist in KMP NFC bridge handler | Ready | High | - | [plans/NS-04-apdu-allowlist.md](./plans/NS-04-apdu-allowlist.md) | - |
|
||||
| NS-05 | LifecycleBridgeHandler type/error semantics on iOS | Ready | Low | - | [plans/NS-05-lifecycle-handler-semantics.md](./plans/NS-05-lifecycle-handler-semantics.md) | - |
|
||||
| NS-06 | Align KMP callback/result contract with canonical SDK types | Done | Medium | NS-01 | [plans/NS-06-kmp-callback-contract-alignment.md](./plans/NS-06-kmp-callback-contract-alignment.md) | - |
|
||||
| NS-07 | Remove legacy `{ type }` shim from native lifecycle handlers | Blocked | Medium | - | - | Blocked on WebView bundle emitting canonical outcomes instead of flat `{ type }` payloads. Requires coordinated change: update `ConfirmIdentificationScreen.tsx` and `ProvingScreen.tsx` to send canonical `VerificationResult`, then remove the `type != null` branch from both Android and iOS `LifecycleBridgeHandler`. |
|
||||
| NS-08 | Ship AAR + XCFramework to MiniPay | Blocked | High | NS-03, NS-09 | [plans/NS-08-ship-artifacts-to-minipay.md](./plans/NS-08-ship-artifacts-to-minipay.md) | ~10 LOC Gradle config for Maven repo target, switch XCFramework to release variants, host XCFramework for SPM. iOS handoff blocked until NS-09 resolves the private NFCPassportReader dependency. |
|
||||
| NS-09 | Make NFCPassportReader fork accessible to external consumers | Ready | High | - | [plans/NS-09-nfcpassportreader-distribution.md](./plans/NS-09-nfcpassportreader-distribution.md) | Decision: make fork public or vendor it. Blocks any external iOS consumer. |
|
||||
|
||||
Allowed statuses: `Ready`, `In Progress`, `Blocked`, `Deferred`, `Done`
|
||||
|
||||
@@ -95,10 +97,12 @@ Allowed statuses: `Ready`, `In Progress`, `Blocked`, `Deferred`, `Done`
|
||||
| Plan | IDs | Status |
|
||||
| -------------------------------------------------------------------------------------------------- | ----- | ------ |
|
||||
| [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) | NS-01 | Done |
|
||||
| [plans/NS-03-publishing-readiness.md](./plans/NS-03-publishing-readiness.md) | NS-03 | Ready |
|
||||
| [plans/NS-03-publishing-readiness.md](./plans/NS-03-publishing-readiness.md) | NS-03 | Done |
|
||||
| [plans/NS-04-apdu-allowlist.md](./plans/NS-04-apdu-allowlist.md) | NS-04 | Ready |
|
||||
| [plans/NS-05-lifecycle-handler-semantics.md](./plans/NS-05-lifecycle-handler-semantics.md) | NS-05 | Ready |
|
||||
| [plans/NS-06-kmp-callback-contract-alignment.md](./plans/NS-06-kmp-callback-contract-alignment.md) | NS-06 | Done |
|
||||
| [plans/NS-08-ship-artifacts-to-minipay.md](./plans/NS-08-ship-artifacts-to-minipay.md) | NS-08 | Ready |
|
||||
| [plans/NS-09-nfcpassportreader-distribution.md](./plans/NS-09-nfcpassportreader-distribution.md) | NS-09 | Ready |
|
||||
|
||||
## Completion Checklist
|
||||
|
||||
@@ -112,6 +116,7 @@ Allowed statuses: `Ready`, `In Progress`, `Blocked`, `Deferred`, `Done`
|
||||
- `NS-01` completed on 2026-03-10 after operator-assisted real-device NFC validation confirmed Android and iOS success and failure paths in the KMP test app. See [plans/NS-01-physical-device-validation.md](./plans/NS-01-physical-device-validation.md) for the validation log.
|
||||
- `NS-06` completed on 2026-03-10. KMP now exposes the canonical `VerificationResult` shape (`success`, `userId`, `verificationId`, `proof`, `claims`, `error`), and `claims` now carries heterogeneous values via `Map<String, Any?>`.
|
||||
- Flat lifecycle `{ type }` payloads remain supported as an internal compatibility shim while the embedded WebView bundle still emits them, but KMP host apps no longer receive a public `VerificationResult.type` field. Tracked as `NS-07` for removal once the WebView sends canonical outcomes.
|
||||
- `NS-03` completed on 2026-03-10. Audit validated AAR and XCFramework generation. Four items block shipping to MiniPay: Maven repo target (~10 LOC config), release XCFramework variants (~3 LOC), hosted XCFramework for SPM, and NFCPassportReader fork accessibility. Tracked as NS-08 and NS-09.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,67 +1,130 @@
|
||||
# Publishing Readiness for AAR and XCFramework
|
||||
|
||||
> Last updated: 2026-03-10
|
||||
> Status: Ready
|
||||
> Status: Done (audit complete)
|
||||
|
||||
- Workstream: native-shells
|
||||
- Backlog IDs: NS-03
|
||||
- Owner: Native Shells
|
||||
- Branch: TBD
|
||||
- PR: TBD
|
||||
- Branch: N/A (audit-only, no code changes)
|
||||
- PR: N/A
|
||||
|
||||
## Why
|
||||
## Goal
|
||||
|
||||
- `Production publishing (npm + AAR + XCFramework)` is still open at the SDK level.
|
||||
- Packaging gaps are easy to lose track of because implementation and release concerns are split across multiple specs.
|
||||
- This plan isolates artifact-readiness work from feature work.
|
||||
|
||||
## Scope
|
||||
|
||||
- Audit current AAR and XCFramework generation paths.
|
||||
- Define missing packaging metadata, versioning, release inputs, and validation steps.
|
||||
- Update the relevant specs so release readiness is tracked in one place.
|
||||
Answer one question: **can MiniPay (or another host app) integrate the KMP SDK today?** Document what works, what doesn't, and the shortest path to a shippable artifact.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Performing the actual release/publish step.
|
||||
- Enterprise publishing (Maven Central signing, full POM compliance, CocoaPods).
|
||||
- RN npm publishing.
|
||||
- Feature changes to handlers or bridge contracts.
|
||||
|
||||
## Files to Modify
|
||||
---
|
||||
|
||||
- `specs/projects/sdk/workstreams/native-shells/SPEC.md`
|
||||
- `specs/projects/sdk/OVERVIEW.md`
|
||||
- packaging/handoff docs if needed
|
||||
## Audit Results
|
||||
|
||||
## Files Not to Modify
|
||||
### Android AAR
|
||||
|
||||
- runtime handler implementations unless packaging audit exposes a required packaging-only change
|
||||
**Status: Builds and publishes to local Maven. Not yet configured for a remote repository.**
|
||||
|
||||
## Preconditions
|
||||
**Validated (ran locally on 2026-03-10):**
|
||||
|
||||
- Physical-device validation should be complete or explicitly waived.
|
||||
- Versioning/release ownership is identified.
|
||||
| Step | Command | Result |
|
||||
| ---------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| Release AAR | `./gradlew :shared:assembleRelease` | `shared/build/outputs/aar/shared-release.aar` |
|
||||
| Maven local publish | `./gradlew :shared:publishToMavenLocal` | Installs AAR + POM + sources + Gradle metadata to `~/.m2/repository/xyz/self/sdk/shared-android/0.1.0/` |
|
||||
| POM transitive deps | Inspected generated POM | Declares kotlin-stdlib, webkit, jmrtd, bouncycastle, mlkit, camera, biometrics with correct scopes |
|
||||
| WebView asset bundling | `copyWebViewAssets` (runs on preBuild) | Copies `webview-app/dist/` into Android assets |
|
||||
|
||||
## Implementation Notes
|
||||
**Not validated:** Consumer resolution (a separate Gradle project resolving `xyz.self.sdk:shared-android:0.1.0` from mavenLocal and compiling against it). The POM and Gradle metadata look correct but this hasn't been tested end-to-end from a clean consumer project.
|
||||
|
||||
- Keep this focused on release readiness, not implementation cleanup.
|
||||
- If packaging requires code changes, split those into child backlog IDs or follow-up plans.
|
||||
**To ship to MiniPay:**
|
||||
|
||||
## Validation
|
||||
1. Add a `publishing { repositories {} }` block pointing to GitHub Packages (or any Maven repo MiniPay can reach). ~10 lines of Gradle config.
|
||||
2. Bump version from `0.1.0` when ready.
|
||||
3. Ideally, validate consumer resolution from a clean project before the first external handoff.
|
||||
|
||||
**Later (not blocking):** ProGuard consumer rules, CI publish job, Maven Central migration if needed.
|
||||
|
||||
### iOS KMP Framework / XCFramework
|
||||
|
||||
**Status: Builds. Shippable via local SPM path or manual XCFramework handoff.**
|
||||
|
||||
**What works:**
|
||||
|
||||
| Step | Command | Result |
|
||||
| ------------------- | ------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| XCFramework | `./gradlew createXCFramework` | `SelfSdk.xcframework` (arm64 device + arm64 simulator) |
|
||||
| SPM Package.swift | Exists | Points to local XCFramework binary target |
|
||||
| Simulator framework | `./gradlew :shared:linkDebugFrameworkIosSimulatorArm64` | Works |
|
||||
|
||||
**To ship to an iOS host app:**
|
||||
|
||||
1. Switch `createXCFramework` from debug to release framework variants. In `build.gradle.kts`, change `linkDebugFrameworkIos*` → `linkReleaseFrameworkIos*` in the `createXCFramework` task's `dependsOn` and path strings (~3 lines).
|
||||
2. Build: `./gradlew createXCFramework` → `shared/build/xcframework/SelfSdk.xcframework`.
|
||||
3. Zip + checksum: `zip -r SelfSdk-0.1.0.xcframework.zip SelfSdk.xcframework && swift package compute-checksum SelfSdk-0.1.0.xcframework.zip`.
|
||||
4. Upload the zip to a GitHub Release (e.g., `kmp-sdk@0.1.0`) or any HTTPS-reachable location.
|
||||
5. Update `packages/kmp-sdk/Package.swift` to use `.binaryTarget(name: "SelfSdk", url: "<release-url>", checksum: "<sha256>")` instead of the local path.
|
||||
6. Tag the release. SPM consumers add the repo URL with the version tag.
|
||||
|
||||
**Ownership:** Whoever cuts the release owns steps 2–6. Version naming follows `packages/kmp-sdk/shared/build.gradle.kts` `version` field. Git tag format: `kmp-sdk@<version>`.
|
||||
|
||||
**Not yet decided:** Whether the host app consumes `SelfSdk.xcframework` (KMP) directly and adds `self-sdk-swift` as a separate SPM dependency, or whether a wrapper package bundles both. Current default: two separate dependencies — KMP XCFramework + Swift companion SPM package. This is fine for MiniPay (single known consumer) but should be revisited if the consumer count grows.
|
||||
|
||||
**Later (not blocking):** x86_64 simulator slice (Intel Macs), CocoaPods podspec, CI automation.
|
||||
|
||||
### Swift Companion Package (`self-sdk-swift`)
|
||||
|
||||
**Status: Works in Xcode and on real devices. `swift build` CLI fails (irrelevant for iOS distribution).**
|
||||
|
||||
**What works:**
|
||||
|
||||
- CI builds via `xcodebuild` for iOS Simulator
|
||||
- Real-device NFC validated through KMP test app
|
||||
- Providers wire into KMP iOS via `SdkProviderRegistry`
|
||||
|
||||
**Known issue:** `swift build` fails because OpenSSL headers don't resolve under SPM CLI on macOS. This doesn't affect iOS distribution (always goes through Xcode).
|
||||
|
||||
**To ship:**
|
||||
|
||||
1. The `NFCPassportReader` fork is private (`git@github.com:selfxyz/NFCPassportReader.git`). Any external consumer needs access. Simplest fix: make the fork public, or vendor it.
|
||||
2. That's the only real blocker. Everything else (versioning, CI) is polish.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What Blocks Shipping
|
||||
|
||||
| What | Effort | Blocks |
|
||||
| ----------------------------------------------------------- | -------------- | ------------------------------- |
|
||||
| Add Maven repository target to Gradle | ~10 LOC config | Android distribution to MiniPay |
|
||||
| Switch XCFramework to release variants | ~3 LOC config | iOS production builds |
|
||||
| Host XCFramework somewhere reachable + update Package.swift | Small | iOS SPM distribution |
|
||||
| Make NFCPassportReader fork accessible | Decision | Any external iOS consumer |
|
||||
|
||||
Everything else (Maven Central, GPG signing, full POM metadata, ProGuard rules, x86_64 slices, CocoaPods, CI publish jobs, version automation) is real work but doesn't block getting artifacts into MiniPay's hands.
|
||||
|
||||
---
|
||||
|
||||
## Validated Commands
|
||||
|
||||
```bash
|
||||
cd packages/kmp-sdk && ./gradlew :shared:assembleDebug
|
||||
cd packages/kmp-sdk && ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
|
||||
cd packages/self-sdk-swift && swift build
|
||||
cd packages/kmp-sdk && ./gradlew :shared:assembleRelease # ✅ AAR
|
||||
cd packages/kmp-sdk && ./gradlew :shared:publishToMavenLocal # ✅ AAR + POM + sources + metadata to ~/.m2
|
||||
cd packages/kmp-sdk && ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64 # ✅ iOS framework
|
||||
cd packages/kmp-sdk && ./gradlew createXCFramework # ✅ XCFramework
|
||||
cd packages/self-sdk-swift && swift build # ❌ Known OpenSSL header issue (not a distribution blocker)
|
||||
```
|
||||
|
||||
**Not yet validated:** Consumer resolution from a clean Gradle project. POM and metadata look correct but no end-to-end consume test has been run.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] AAR generation path documented and validated
|
||||
- [ ] XCFramework or framework packaging path documented and validated
|
||||
- [ ] Remaining blockers explicitly listed
|
||||
- [ ] Backlog row updated
|
||||
- [x] AAR generation path documented and validated
|
||||
- [x] XCFramework or framework packaging path documented and validated
|
||||
- [x] Remaining blockers explicitly listed
|
||||
- [x] Backlog row updated
|
||||
|
||||
## Status Log
|
||||
|
||||
- 2026-03-10: Created from SDK publishing follow-up.
|
||||
- 2026-03-10: Audit complete. Artifacts build. Four items block shipping to external consumers; all are small config or decision items.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Ship AAR + XCFramework to MiniPay
|
||||
|
||||
> Last updated: 2026-03-10
|
||||
> Status: Ready
|
||||
|
||||
- Workstream: native-shells
|
||||
- Backlog IDs: NS-08
|
||||
- Owner: Native Shells
|
||||
- Depends on: NS-03
|
||||
- Branch: TBD
|
||||
- PR: TBD
|
||||
|
||||
## Goal
|
||||
|
||||
Make KMP SDK artifacts consumable by MiniPay. Android via Maven repository, iOS via SPM with hosted XCFramework.
|
||||
|
||||
## Scope
|
||||
|
||||
### Android
|
||||
|
||||
1. Add `publishing { repositories { maven { ... } } }` block to `shared/build.gradle.kts` targeting GitHub Packages (or whichever Maven repo MiniPay can resolve).
|
||||
2. Validate: run `./gradlew :shared:publish`, then resolve `xyz.self.sdk:shared-android:0.1.0` from a clean consumer Gradle project.
|
||||
|
||||
### iOS
|
||||
|
||||
1. Switch `createXCFramework` task from debug to release variants (~3 lines in `build.gradle.kts`).
|
||||
2. Build, zip, compute checksum, upload to GitHub Release.
|
||||
3. Update `Package.swift` binary target from local path to release URL + checksum.
|
||||
4. Tag release. Validate: add SPM dependency from a clean Xcode project.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
- `packages/kmp-sdk/shared/build.gradle.kts` — add publishing repository block
|
||||
- `packages/kmp-sdk/shared/build.gradle.kts` — switch `createXCFramework` to release variants
|
||||
- `packages/kmp-sdk/Package.swift` — remote binary target URL
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Maven Central (GPG signing, full POM metadata). GitHub Packages or equivalent is sufficient.
|
||||
- CocoaPods. SPM is sufficient for MiniPay.
|
||||
- CI automation for publishing. Manual release is fine for now.
|
||||
|
||||
## Validation
|
||||
|
||||
```bash
|
||||
# Android
|
||||
cd packages/kmp-sdk && ./gradlew :shared:publish
|
||||
# Then from a separate consumer project: resolve xyz.self.sdk:shared-android:<version>
|
||||
|
||||
# iOS
|
||||
cd packages/kmp-sdk && ./gradlew createXCFramework
|
||||
# Then from a clean Xcode project: add SPM dependency and build
|
||||
```
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] MiniPay can resolve the Android AAR from a Maven repository
|
||||
- [ ] MiniPay can add the iOS XCFramework via SPM from a hosted URL
|
||||
- [ ] Consumer resolution validated end-to-end on both platforms
|
||||
@@ -0,0 +1,42 @@
|
||||
# NFCPassportReader Distribution Strategy
|
||||
|
||||
> Last updated: 2026-03-10
|
||||
> Status: Ready
|
||||
|
||||
- Workstream: native-shells
|
||||
- Backlog IDs: NS-09
|
||||
- Owner: Native Shells
|
||||
- Branch: TBD
|
||||
- PR: TBD
|
||||
|
||||
## Goal
|
||||
|
||||
Make `self-sdk-swift` consumable by external iOS host apps. The blocker is the private `NFCPassportReader` fork dependency.
|
||||
|
||||
## Problem
|
||||
|
||||
`self-sdk-swift/Package.swift` depends on `git@github.com:selfxyz/NFCPassportReader.git` (SSH, private fork). Any external consumer needs GitHub SSH access to the selfxyz org to resolve this dependency. MiniPay (or any host app outside the org) can't build without it.
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Effort | Trade-off |
|
||||
| ----------------------------------------------------- | ------ | ------------------------------------------------------------------------------- |
|
||||
| Make the fork public | Low | Exposes fork changes; may have upstream license implications to check |
|
||||
| Vendor NFCPassportReader source into `self-sdk-swift` | Medium | No external dependency; increases repo size; must manually sync upstream |
|
||||
| Pre-build NFCPassportReader as XCFramework binary | Medium | Consumers get a binary; but adds a build/release step for the dependency itself |
|
||||
| Switch Package.swift to HTTPS + access token | Low | Still requires credentials; doesn't solve the external consumer problem |
|
||||
|
||||
## Recommendation
|
||||
|
||||
Make the fork public unless there's a specific reason it's private. Lowest effort, solves the problem completely.
|
||||
|
||||
## Scope
|
||||
|
||||
1. Decide on approach (decision, not code).
|
||||
2. Execute the chosen option.
|
||||
3. If the fork remains an external dependency, update `packages/self-sdk-swift/Package.swift` from the SSH URL to an HTTPS URL and pin a tag/revision that external consumers can resolve.
|
||||
4. Validate: `self-sdk-swift` resolves from a clean environment without org SSH credentials.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] An external iOS consumer can resolve all `self-sdk-swift` dependencies without selfxyz org credentials
|
||||
Reference in New Issue
Block a user