document remote tsswift workflow and bump to 0.6.0
CI / test (push) Has been cancelled

This commit is contained in:
2026-04-20 19:18:10 +00:00
parent 75f5a4e7e8
commit c908187840
3 changed files with 124 additions and 50 deletions
+118 -44
View File
@@ -1,70 +1,144 @@
# idp.global Swift App # 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 - iPhone pairing starts on a welcome screen and then opens QR scanning explicitly.
- NFC authentication now attaches a signed GPS position on supported iPhone hardware - QR pairing supports a manual paste fallback when camera scanning is unavailable.
- Mocked approval inbox for accepting or rejecting identity requests - NFC pairing and NFC identity proof attach a signed GPS position on supported iPhones.
- Notification center with local notification permission flow and a test notification trigger - The app uses the live `idp.global` backend by default for pairing, dashboard loading, approvals, and alerts.
- Apple Watch companion target with a compact approval-first dashboard and request detail flow - The Apple Watch companion and widgets live in the same Xcode project and build with the main app scheme.
- Shared app state and mock backend boundary so a real API can be connected later - `MockIDPService` still exists for previews and test scaffolding, but normal runtime uses `LiveIDPService`.
## Open the project ## Repo Layout
1. Open `swift/IDPGlobal.xcodeproj`. - root `package.json`
2. Build the `IDPGlobal` scheme for: - root `.smartconfig.json`
- `My Mac` - Swift project at `swift/IDPGlobal.xcodeproj`
- an iPad simulator
- an iPhone simulator
3. Build the `IDPGlobalWatch` scheme for an Apple Watch simulator when you want to verify the companion experience.
## 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 <builder-name> \
--host <ssh-host> \
--root-dir <remote-project-root> \
--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": "<builder-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: From the repo root:
```bash ```bash
corepack pnpm install
corepack pnpm swift:doctor corepack pnpm swift:doctor
corepack pnpm swift:emulators corepack pnpm swift:emulators
corepack pnpm swift:build 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:test
corepack pnpm swift:run corepack pnpm run swift:run -- --platform ios
corepack pnpm run swift:run -- --platform ipad
corepack pnpm swift:watch corepack pnpm swift:watch
``` ```
This repo now follows the same layout as the other Swift app repos: Notes:
- git root at the repo root - `swift:build` builds the configured macOS, iPhone, and iPad matrix.
- root `package.json` - `swift:test` runs the macOS test target.
- root `.smartconfig.json` - `swift:run` without extra flags follows the configured default platform, which is currently `macos`.
- Swift app content under `swift/` - `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 If you are working directly on a Mac instead of through `tsswift`, open:
- `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
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. - 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.
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. - NFC flows are for supported iPhone hardware and include signed location evidence.
## 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
+1 -1
View File
@@ -13,6 +13,6 @@
"swift:launch": "tsswift launch --path swift/IDPGlobal.xcodeproj" "swift:launch": "tsswift launch --path swift/IDPGlobal.xcodeproj"
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsswift": "0.5.2" "@git.zone/tsswift": "0.6.0"
} }
} }
+5 -5
View File
@@ -9,8 +9,8 @@ importers:
.: .:
devDependencies: devDependencies:
'@git.zone/tsswift': '@git.zone/tsswift':
specifier: 0.5.2 specifier: 0.6.0
version: 0.5.2 version: 0.6.0
packages: packages:
@@ -39,8 +39,8 @@ packages:
'@design.estate/dees-element@2.2.4': '@design.estate/dees-element@2.2.4':
resolution: {integrity: sha512-O9cA6flBMMd+pBwMQrZXwAWel9yVxgokolb+Em6gvkXxPJ0P/B5UDn4Vc2d4ts3ta55PTBm+l2dPeDVGx/bl7Q==} resolution: {integrity: sha512-O9cA6flBMMd+pBwMQrZXwAWel9yVxgokolb+Em6gvkXxPJ0P/B5UDn4Vc2d4ts3ta55PTBm+l2dPeDVGx/bl7Q==}
'@git.zone/tsswift@0.5.2': '@git.zone/tsswift@0.6.0':
resolution: {integrity: sha512-ZB8d9gBykrV0EhrOSo600YEoZpIO08xNP0T5qS5CV3vxymSAP86yY5epYazqhnZ9lmWkKUYDgDvc12jVYdeTpA==} resolution: {integrity: sha512-XrvzVYml822tWoT9Bogv1GFRf0V6JJnYGxQXZIOqjlzyHQXJSwMD9vh2uePsLn0LfgvEcTvXe3SL+NSlDBuvYw==}
hasBin: true hasBin: true
'@isaacs/cliui@9.0.0': '@isaacs/cliui@9.0.0':
@@ -993,7 +993,7 @@ snapshots:
- supports-color - supports-color
- vue - vue
'@git.zone/tsswift@0.5.2': '@git.zone/tsswift@0.6.0':
dependencies: dependencies:
'@push.rocks/smartcli': 4.0.20 '@push.rocks/smartcli': 4.0.20
'@push.rocks/smartconfig': 6.1.0 '@push.rocks/smartconfig': 6.1.0