From c90818784024240e9183a314918c1daffda29ddf Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Mon, 20 Apr 2026 19:18:10 +0000 Subject: [PATCH] document remote tsswift workflow and bump to 0.6.0 --- README.md | 162 +++++++++++++++++++++++++++++++++++-------------- package.json | 2 +- pnpm-lock.yaml | 10 +-- 3 files changed, 124 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index c35d7e2..89218ff 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,144 @@ # idp.global Swift App -Multiplatform SwiftUI scaffold for the personal `idp.global` companion app on iPhone, iPad, Mac, and Apple Watch. +Multiplatform SwiftUI passport companion for `idp.global` on iPhone, iPad, Mac, and Apple Watch. -## Included in this first pass +## Current App Behavior -- QR and NFC-based device pairing flows with a seeded preview payload fallback -- NFC authentication now attaches a signed GPS position on supported iPhone hardware -- Mocked approval inbox for accepting or rejecting identity requests -- Notification center with local notification permission flow and a test notification trigger -- Apple Watch companion target with a compact approval-first dashboard and request detail flow -- Shared app state and mock backend boundary so a real API can be connected later +- iPhone pairing starts on a welcome screen and then opens QR scanning explicitly. +- QR pairing supports a manual paste fallback when camera scanning is unavailable. +- NFC pairing and NFC identity proof attach a signed GPS position on supported iPhones. +- The app uses the live `idp.global` backend by default for pairing, dashboard loading, approvals, and alerts. +- The Apple Watch companion and widgets live in the same Xcode project and build with the main app scheme. +- `MockIDPService` still exists for previews and test scaffolding, but normal runtime uses `LiveIDPService`. -## Open the project +## Repo Layout -1. Open `swift/IDPGlobal.xcodeproj`. -2. Build the `IDPGlobal` scheme for: - - `My Mac` - - an iPad simulator - - an iPhone simulator -3. Build the `IDPGlobalWatch` scheme for an Apple Watch simulator when you want to verify the companion experience. +- root `package.json` +- root `.smartconfig.json` +- Swift project at `swift/IDPGlobal.xcodeproj` -## tsswift workflow +## tsswift Setup + +This repo is configured for `tsswift` from the repo root and expects a named global remote builder. + +Install tooling: + +```bash +corepack pnpm install +``` + +Configure a global remote macOS builder once: + +```bash +corepack pnpm exec tsswift config -g add-builder \ + --name \ + --host \ + --root-dir \ + --platforms macos,ios,ipad +``` + +The global builder registry lives at: + +```text +~/.git.zone/tsswift/config.json +``` + +Verify it with: + +```bash +corepack pnpm exec tsswift config list-builders +corepack pnpm exec tsswift config show +``` + +## Remote Builder Behavior + +This project does not keep per-repo SSH details inside `.smartconfig.json`. +Instead, it references a named builder, and `tsswift` resolves that builder from the global registry in `~/.git.zone/tsswift/config.json`. + +How it works: + +- `tsswift` syncs the repo to the configured remote project root via `rsync` +- `xcodebuild`, `simctl`, and simulator boot or launch commands execute on the remote macOS builder over SSH +- the local machine only orchestrates the workflow; Apple platform builds happen on the builder +- the selected simulator is opened by the requested device identifier instead of reviving a previously used simulator +- simulator builds are pinned to the builder machine's native architecture + +Prerequisites: + +- working SSH access to the remote builder host +- a configured global `tsswift` builder entry +- local permission to run `ssh` and `rsync` + +Quick verification: + +```bash +corepack pnpm exec tsswift config -g list-builders +corepack pnpm swift:doctor +``` + +`swift:doctor` should report the resolved remote builder and remote project root. + +This repo's `.smartconfig.json` already points at that builder by name: + +```json +"remoteBuilder": { + "name": "" +} +``` + +Current project defaults: + +- default scheme: `IDPGlobal` +- default configuration: `Debug` +- default run platform: `macos` +- build platforms: `macos`, `ios`, `ipad` +- test platform: `macos` +- preferred iPhone and iPad simulators are configured in `.smartconfig.json` +- derived data path: `swift/.build/xcode-derived-data` + +`tsswift` pins simulator builds to the builder machine's native architecture and opens the selected simulator device directly instead of reviving a previously used iPhone. + +## Common Commands From the repo root: ```bash -corepack pnpm install corepack pnpm swift:doctor corepack pnpm swift:emulators corepack pnpm swift:build +corepack pnpm swift:build:macos +corepack pnpm run swift:build -- --platform ios +corepack pnpm run swift:build -- --platform ipad corepack pnpm swift:test -corepack pnpm swift:run +corepack pnpm run swift:run -- --platform ios +corepack pnpm run swift:run -- --platform ipad corepack pnpm swift:watch ``` -This repo now follows the same layout as the other Swift app repos: +Notes: -- git root at the repo root -- root `package.json` -- root `.smartconfig.json` -- Swift app content under `swift/` +- `swift:build` builds the configured macOS, iPhone, and iPad matrix. +- `swift:test` runs the macOS test target. +- `swift:run` without extra flags follows the configured default platform, which is currently `macos`. +- `swift:run -- --platform ios` boots the configured remote iPhone simulator, installs the app, and launches it. +- `swift:run -- --platform ipad` does the same for the configured remote iPad simulator. -Current `tsswift` behavior here: +## Direct Xcode Use -- `build` targets macOS, iPhone Simulator, and iPad Simulator in parallel -- `test` targets macOS -- `run` defaults to macOS unless you pass `--platform ios` or `--platform ipad` -- `watch` rebuilds and relaunches macOS, iPhone, and iPad app instances on file changes +If you are working directly on a Mac instead of through `tsswift`, open: -The Apple Watch companion is still part of the Xcode project, but `tsswift` is currently configured around the main `IDPGlobal` app targets only. +```text +swift/IDPGlobal.xcodeproj +``` -## Mock QR payload +Useful targets and schemes: -The app seeds this pairing payload on first launch: +- `IDPGlobal` for the main app +- `IDPGlobalWatch` for the watch app +- `IDPGlobalWidgets` for widgets -`idp.global://pair?token=swiftapp-demo-berlin&origin=code.foss.global&device=Safari%20on%20Berlin%20MBP` +## Pairing Notes -You can paste it manually, scan it as a QR code, or use the preview pairing action while the backend is still mocked. - -For NFC authentication, the app reads the pairing payload from the tag, captures the current device location, signs that GPS position, and submits both together. - -## Next integration step - -Replace `MockIDPService` with a live service that: - -- exchanges the pairing payload and signed NFC location proof for a session token -- loads approval requests and notifications from the backend -- posts approval decisions back to `idp.global` -- syncs session and request state between iPhone and Apple Watch, likely through a shared backend session or WatchConnectivity bridge +- Start a fresh pairing flow from the `idp.global` web session you want to trust. +- Scan the QR shown by that web flow, or paste the pairing link manually if camera access is unavailable. +- NFC flows are for supported iPhone hardware and include signed location evidence. diff --git a/package.json b/package.json index 8eae0fb..bac7de7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,6 @@ "swift:launch": "tsswift launch --path swift/IDPGlobal.xcodeproj" }, "devDependencies": { - "@git.zone/tsswift": "0.5.2" + "@git.zone/tsswift": "0.6.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f60f53..dc1bebe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@git.zone/tsswift': - specifier: 0.5.2 - version: 0.5.2 + specifier: 0.6.0 + version: 0.6.0 packages: @@ -39,8 +39,8 @@ packages: '@design.estate/dees-element@2.2.4': resolution: {integrity: sha512-O9cA6flBMMd+pBwMQrZXwAWel9yVxgokolb+Em6gvkXxPJ0P/B5UDn4Vc2d4ts3ta55PTBm+l2dPeDVGx/bl7Q==} - '@git.zone/tsswift@0.5.2': - resolution: {integrity: sha512-ZB8d9gBykrV0EhrOSo600YEoZpIO08xNP0T5qS5CV3vxymSAP86yY5epYazqhnZ9lmWkKUYDgDvc12jVYdeTpA==} + '@git.zone/tsswift@0.6.0': + resolution: {integrity: sha512-XrvzVYml822tWoT9Bogv1GFRf0V6JJnYGxQXZIOqjlzyHQXJSwMD9vh2uePsLn0LfgvEcTvXe3SL+NSlDBuvYw==} hasBin: true '@isaacs/cliui@9.0.0': @@ -993,7 +993,7 @@ snapshots: - supports-color - vue - '@git.zone/tsswift@0.5.2': + '@git.zone/tsswift@0.6.0': dependencies: '@push.rocks/smartcli': 4.0.20 '@push.rocks/smartconfig': 6.1.0