This commit is contained in:
@@ -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 <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:
|
||||
|
||||
```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.
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+5
-5
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user