# XcodeGen project spec — regenerate with: cd ios && xcodegen generate
# The generated WebTerm.xcodeproj is NOT committed (see ios/.gitignore).
#
# TOOLCHAIN DEVIATION (recorded per plan §7 T-iOS-1): the plan names
# "default MainActor isolation" (SWIFT_DEFAULT_ACTOR_ISOLATION), which is
# Swift 6.2+/Xcode 26 only. On Swift 6.1 / Xcode 16.3 the closest supported
# equivalent is Swift 6 language mode + strict concurrency, with explicit
# @MainActor annotations where isolation is required.
name: WebTerm

options:
  bundleIdPrefix: com.yaojia
  deploymentTarget:
    iOS: "17.0"
  createIntermediateGroups: true

settings:
  base:
    SWIFT_VERSION: "6.0"                  # Swift 6 language mode
    SWIFT_STRICT_CONCURRENCY: complete
    IPHONEOS_DEPLOYMENT_TARGET: "17.0"
    TARGETED_DEVICE_FAMILY: "1,2"        # iPhone + iPad (T-iPad-1; adaptive layout)
    CODE_SIGN_STYLE: Automatic

packages:
  WireProtocol:
    path: Packages/WireProtocol
  SessionCore:
    path: Packages/SessionCore
  HostRegistry:
    path: Packages/HostRegistry
  APIClient:
    path: Packages/APIClient
  TestSupport:
    path: Packages/TestSupport   # test doubles — WebTermTests only, never the app target
  # SwiftTerm is the ONLY third-party dependency, attached to the App target
  # ONLY (plan §2) — packages must never import it.
  SwiftTerm:
    url: https://github.com/migueldeicaza/SwiftTerm
    from: 1.13.0

targets:
  WebTerm:
    type: application
    platform: iOS
    sources:
      - App/WebTerm
    dependencies:
      - package: WireProtocol
      - package: SessionCore
      - package: HostRegistry
      - package: APIClient
      - package: SwiftTerm
    settings:
      base:
        PRODUCT_BUNDLE_IDENTIFIER: com.yaojia.webterm
        # Target-level on purpose (T-iOS-19 finding): XcodeGen's target platform
        # default overrides a project-level value. iPad adaptation (T-iPad-1)
        # opens this to iPhone + iPad; the adaptive layout (LayoutPolicy /
        # NavigationSplitView, T-iPad-2) makes the iPad layout first-class.
        TARGETED_DEVICE_FAMILY: "1,2"
    info:
      path: App/WebTerm/Resources/Info.plist
      properties:
        CFBundleDisplayName: WebTerm
        UILaunchScreen: {}
        # Deep-link scheme (P1 T-iOS-22): webterminal://open?host=<id>&join=<uuid>
        # Registered here by the orchestrator (project.yml coordination point);
        # all parsing/validation lives in DeepLinkRouter (untrusted input).
        CFBundleURLTypes:
          - CFBundleURLName: com.yaojia.webterm.deeplink
            CFBundleURLSchemes: [webterminal]
        # iPhone: portrait + both landscapes (no upside-down — matches P0).
        UISupportedInterfaceOrientations:
          - UIInterfaceOrientationPortrait
          - UIInterfaceOrientationLandscapeLeft
          - UIInterfaceOrientationLandscapeRight
        # iPad (T-iPad-1): all four orientations — iPad users hold it any way,
        # and Split View / Stage Manager assume full orientation freedom.
        UISupportedInterfaceOrientations~ipad:
          - UIInterfaceOrientationPortrait
          - UIInterfaceOrientationPortraitUpsideDown
          - UIInterfaceOrientationLandscapeLeft
          - UIInterfaceOrientationLandscapeRight
        # ── Security-critical keys, transcribed verbatim from PLAN_IOS_CLIENT §5.2 ──
        # NO NSAllowsArbitraryLoads anywhere (release OR debug): the five CIDR
        # exceptions below cover LAN + hotspot + Tailscale CGNAT + simulator
        # loopback, so no arbitrary-loads escape hatch is needed in P0.
        # T-iOS-19 re-verifies all five CIDR blocks in the release ipa.
        NSAppTransportSecurity:
          NSAllowsLocalNetworking: true   # only covers .local / dotless hostnames, not bare IPs
          NSExceptionDomains:             # bare IPs use CIDR exceptions (iOS 17+ semantics)
            "192.168.0.0/16":
              NSExceptionAllowsInsecureHTTPLoads: true
            "10.0.0.0/8":
              NSExceptionAllowsInsecureHTTPLoads: true
            "172.16.0.0/12":              # RFC1918 third block (iPhone hotspot 172.20.10.x / corp LAN)
              NSExceptionAllowsInsecureHTTPLoads: true
            "100.64.0.0/10":              # Tailscale CGNAT
              NSExceptionAllowsInsecureHTTPLoads: true
            "127.0.0.0/8":                # simulator dev-loop (CIDR, not a single-IP key — DevForums 6205)
              NSExceptionAllowsInsecureHTTPLoads: true
        NSLocalNetworkUsageDescription: "连接你自己电脑上的 web-terminal 服务器"
        NSCameraUsageDescription: "扫描 web 终端的配对二维码"

  # Unit-test bundle for App-target logic (ViewModels & pure UI components,
  # W3 T-iOS-11…14). Added by the orchestrator as a coordination point
  # (project.yml is T-iOS-1's Owns; same precedent as the W1 manifest wiring).
  # Coverage GATE still counts only the 4 packages (plan §9) — these tests
  # exist for correctness, not for the gate.
  WebTermTests:
    type: bundle.unit-test
    platform: iOS
    sources:
      - App/WebTermTests
    dependencies:
      - target: WebTerm
      - package: WireProtocol
      - package: SessionCore
      - package: HostRegistry
      - package: APIClient
      - package: TestSupport
    settings:
      base:
        GENERATE_INFOPLIST_FILE: true
        TARGETED_DEVICE_FAMILY: "1,2"
        TEST_HOST: "$(BUILT_PRODUCTS_DIR)/WebTerm.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/WebTerm"
        BUNDLE_LOADER: "$(TEST_HOST)"

  # XCUITest — exactly ONE scripted happy path per plan §9 (T-iOS-18 finding):
  # pair via manual entry against a live loopback server → attach → type →
  # approve a held gate. Kept deliberately minimal (fragile-surface rule).
  WebTermUITests:
    type: bundle.ui-testing
    platform: iOS
    sources:
      - App/WebTermUITests
    dependencies:
      - target: WebTerm
    settings:
      base:
        GENERATE_INFOPLIST_FILE: true
        TARGETED_DEVICE_FAMILY: "1,2"
        TEST_TARGET_NAME: WebTerm

schemes:
  WebTerm:
    build:
      targets:
        WebTerm: all
        WebTermTests: [test]
    run:
      config: Debug
    test:
      config: Debug
      targets:
        - WebTermTests
  # Separate scheme so the slow UI pass never gates the fast unit loop; CI
  # runs it as its own leg (see .github/workflows/ios.yml).
  WebTermUITests:
    build:
      targets:
        WebTerm: all
        WebTermUITests: [test]
    test:
      config: Debug
      targets:
        - WebTermUITests
