Files
gstack/test/fixtures/ios-qa/FixtureApp/project.yml
T
Garry Tan f4f8b9f966 fix(ios): 3 architecture bugs surfaced by real-iPhone device test
End-to-end verification on a connected iPhone 17 Pro Max via CoreDevice
tunnel exposed three bugs the TS-stubbed and macOS-XCTest layers missed:

1. acceptLocalOnly=true was too tight. Network.framework's "local" gate
   only allows ::1 / 127.0.0.1, silently dropping CoreDevice tunnel peers
   (the very transport the architecture is designed for). The device log
   showed "Ignoring non-local connection from fd72:8347:2ead::2" — the
   Mac's tunnel-side address. Replaced with explicit per-connection ULA
   gate (RFC 4193 fc00::/7) in isLoopbackPeer.

2. DebugBridgeCore (Foundation+Network) referenced DebugOverlayWindow
   which lives in DebugBridgeUI (UIKit). Backwards module dep. Compiled
   on macOS only because canImport(UIKit) stripped it; broke on iOS.
   Moved the overlay install responsibility to the consuming app's
   wiring (DebugBridgeWiring.swift.template already shows the pattern).

3. @Observable macro + @Snapshotable property wrapper conflict. Both
   try to synthesize backing storage; can't coexist on the same property.
   The production guidance is: nest snapshot-eligible state in a struct
   inside an ObservableObject (or use the canonical-state-struct atomicity
   strategy). Fixture switched to a plain class to demonstrate.

Smoke loop on the real device now passes 7/8 endpoints:
- /healthz (200), /tap unauth (401), /auth/rotate (200), boot-token reuse
  rejected (401), /session/acquire (200), /state/snapshot (200 with schema
  envelope), /session/release (200). /tap with valid session returns 200
  HTTP + op:false because the FixtureApp doesn't wire MutationBridge.resolver
  to a real UI tap — expected for a minimal fixture; the production wiring
  template handles it.

Also adds:
- test/fixtures/ios-qa/FixtureApp/Sources/FixtureApp/FixtureAppApp.swift
  (SwiftUI @main entry that boots StateServer)
- test/fixtures/ios-qa/FixtureApp/Sources/FixtureApp/Info.plist
- test/fixtures/ios-qa/FixtureApp/project.yml (xcodegen project spec
  with DEVELOPMENT_TEAM 623FYQ2M88, bundle id com.gstack.iosqa.fixture)

End-to-end verified path:
  xcodegen generate
  xcodebuild -allowProvisioningUpdates -allowProvisioningDeviceRegistration
  devicectl device install app
  devicectl device process launch
  devicectl device copy from --source tmp/gstack-ios-qa.token
  curl -6 http://[<corodevice-ipv6>]:9999/...
2026-05-19 21:59:02 -07:00

50 lines
1.4 KiB
YAML

name: FixtureApp
options:
deploymentTarget:
iOS: "16.0"
bundleIdPrefix: com.gstack.iosqa
developmentLanguage: en
createIntermediateGroups: true
settings:
DEVELOPMENT_TEAM: 623FYQ2M88
CODE_SIGN_STYLE: Automatic
ENABLE_USER_SCRIPT_SANDBOXING: NO
# Personal-team bundle IDs are scoped per-team; this prefix is unique.
PRODUCT_BUNDLE_IDENTIFIER: com.gstack.iosqa.fixture
# Local SPM package providing DebugBridgeCore + DebugBridgeUI as dependencies.
# packages keyword (with `path:`) means a sibling local package next to project.yml.
packages:
DebugBridge:
path: .
targets:
FixtureApp:
type: application
platform: iOS
deploymentTarget: "16.0"
sources:
- path: Sources/FixtureApp
dependencies:
- package: DebugBridge
product: DebugBridgeCore
- package: DebugBridge
product: DebugBridgeUI
info:
path: Sources/FixtureApp/Info.plist
properties:
CFBundleDisplayName: ios-qa fixture
UILaunchScreen: {}
UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait]
UIRequiredDeviceCapabilities: [arm64]
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.gstack.iosqa.fixture
DEVELOPMENT_TEAM: 623FYQ2M88
CODE_SIGN_STYLE: Automatic
TARGETED_DEVICE_FAMILY: "1"
SWIFT_VERSION: "5.9"
IPHONEOS_DEPLOYMENT_TARGET: "16.0"
ENABLE_PREVIEWS: YES