-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproject.yml
More file actions
199 lines (197 loc) · 9.98 KB
/
Copy pathproject.yml
File metadata and controls
199 lines (197 loc) · 9.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
name: graffito
options:
bundleIdPrefix: com.objsal
createIntermediateGroups: true
settings:
base:
MARKETING_VERSION: "1.0"
CURRENT_PROJECT_VERSION: "72"
targets:
graffito:
type: application
platform: iOS
deploymentTarget: "16.0"
# Wires graffito-uitests (the tap-server XCUITest target, below) into
# this target's AUTOGENERATED scheme's Test action — xcodegen does not
# do this on its own just because a bundle.ui-testing target sets
# TEST_TARGET_NAME back at this target; without this, `xcodebuild
# build-for-testing -scheme graffito` builds only the app. Purely
# additive: every other property of this target is unchanged.
scheme:
testTargets:
- graffito-uitests
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.byteapps.graffito
PRODUCT_NAME: graffito
EXECUTABLE_NAME: graffito
CODE_SIGN_STYLE: Automatic
# Set via env at `xcodegen generate` time (not committed) — see
# ../private/graffito/signing.env for the local value.
DEVELOPMENT_TEAM: ${DEVELOPMENT_TEAM}
GENERATE_INFOPLIST_FILE: NO
# Single-size 1024px icon in Assets.xcassets/AppIcon.appiconset,
# rendered from the full-bleed variant of assets/icon/icon.svg
# (iOS applies its own corner mask).
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
# iCloud-contacts feature (2026-07-20): NSUbiquitousKeyValueStore
# needs the ubiquity-kvstore-identifier capability — same identifier
# as the macOS target (graffito-mac.entitlements) so the two
# platforms share one KV store.
CODE_SIGN_ENTITLEMENTS: graffito-ios.entitlements
# iPhone ONLY (Sal 2026-07-26). Without this xcodegen defaults an iOS
# app to "1,2" (iPhone + iPad), and App Store submission then demands a
# full iPad Pro 12.9" screenshot set for a UI that is phone-shaped and
# portrait-only anyway (STATE_ERROR.SCREENSHOT_REQUIRED
# .APP_IPAD_PRO_3GEN_129). Widening this back to iPad means shipping
# iPad screenshots with it.
TARGETED_DEVICE_FAMILY: "1"
info:
path: Info.plist
properties:
CFBundleDisplayName: Graffito
CFBundleExecutable: graffito
# xcodegen regenerates Info.plist from these properties on every
# `generate` — without an explicit entry here it defaults
# CFBundleVersion to "1" every time, silently discarding
# settings.base.CURRENT_PROJECT_VERSION above (which nothing else
# references). Point it at that setting so bumping it up top is the
# one place that actually takes effect.
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)"
NSCameraUsageDescription: "Scan QR codes (keys, addresses, PSBTs, sync bundles)."
NSFaceIDUsageDescription: "Unlock your notes key to reveal your backup."
# Dark launch background (matches Pal.bg) so the cold-start flash isn't
# white — the colour lives in Assets.xcassets/LaunchBackground.colorset.
UILaunchScreen:
UIColorName: LaunchBackground
ITSAppUsesNonExemptEncryption: false
# Portrait-only, phone-shaped UI. UIRequiresFullScreen opts out of iPad
# multitasking so a single-orientation set is allowed (App Store
# validation rejects portrait-only universal apps otherwise — code 90474).
UIRequiresFullScreen: true
UISupportedInterfaceOrientations:
- UIInterfaceOrientationPortrait
sources:
- Assets.xcassets
# Required-reason API declarations (mandatory for iOS since 2024-05-01).
# Must be bundled at the .app root, which is what a plain source entry
# does. Shared verbatim with the macOS target below.
- PrivacyInfo.xcprivacy
postCompileScripts:
- name: Build Rust binary with cargo
script: |
bash "${SRCROOT}/build_ios.bash" graffito
outputFiles:
- $(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)
# "Tap server" XCUITest — runs ON the device, polls a Mac-side HTTP
# server for coordinate-based commands (tap/swipe/type/pasteboard/
# screenshot), executes them against the running `graffito` app, and
# reports results back. Exists because Slint renders to a single Metal
# surface: the accessibility tree is EMPTY, so element-based XCUITest
# queries find nothing and hang until timeout — every interaction here
# is coordinate-based (see uitests/TapServer.swift). This is the ONLY
# route to driving a physical, wirelessly-connected iPhone: idb needs
# the legacy AMDevice/USB path and does not see CoreDevice-managed
# iOS 17+ devices, while `devicectl` handles install/launch/terminate
# but has no UI-interaction verb of its own.
graffito-uitests:
type: bundle.ui-testing
platform: iOS
deploymentTarget: "16.0"
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.byteapps.graffito.uitests
CODE_SIGN_STYLE: Automatic
DEVELOPMENT_TEAM: ${DEVELOPMENT_TEAM}
GENERATE_INFOPLIST_FILE: YES
# Associates this bundle with the `graffito` app as its host.
# NOT sufficient on its own: xcodegen does NOT add a UI test target
# to its host's autogenerated scheme from TEST_TARGET_NAME alone —
# without the `scheme: testTargets:` block on the `graffito` target
# above, `xcodebuild build-for-testing` builds the app and ZERO test
# bundles, and the later `test-without-building` fails with
# "There are no test bundles available to test" (2026-09-12).
TEST_TARGET_NAME: graffito
# The runner polls the Mac's tap server over the LAN, and iOS gates
# that behind Local Network Privacy. A refusal looks NOTHING like a
# permission error: every request fails with `unsatisfied (Local
# network prohibited)` and NSURLError -1009 "The Internet connection
# appears to be offline" — i.e. it reads as a dead network (2026-09-12:
# ~1170 silent refusals across a 20-minute run).
#
# This key is set for documentation only and is NOT the fix: the
# string below lands in the inner .xctest bundle, while the process
# actually opening the sockets is graffito-uitests-Runner.app, whose
# Info.plist Xcode generates from its own XCTRunner template — that
# template ALREADY carries NSLocalNetworkUsageDescription ("Access is
# necessary for automated testing"). So the grant cannot be fixed
# from this file at all: it must be allowed ON THE DEVICE, at
# Settings > Privacy & Security > Local Network, for the RUNNER app
# (not for Graffito — they are separate bundles).
INFOPLIST_KEY_NSLocalNetworkUsageDescription: "Connects to the test harness on your Mac to drive UI automation."
sources:
- uitests
# macOS Mac App Store build. Same bundle id as iOS → Universal Purchase.
# App-Sandboxed (graffito-mac.entitlements) and Mac-App-Store-signed.
# The Rust bin is built (universal, per $ARCHS) and code-signed by Xcode
# via the build_mac.bash post-compile step — mirrors build_ios.bash.
graffito-mac:
type: application
platform: macOS
deploymentTarget: "12.0"
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.byteapps.graffito
# Bundle is "Graffito.app" (user-visible in Finder/switcher). The
# Unix executable stays graffito so build_mac.bash keeps copying
# the Rust binary to Contents/MacOS/graffito.
PRODUCT_NAME: Graffito
EXECUTABLE_NAME: graffito
CODE_SIGN_STYLE: Automatic
DEVELOPMENT_TEAM: ${DEVELOPMENT_TEAM}
GENERATE_INFOPLIST_FILE: NO
# Separate mac-idiom icon set (16–512 @1x/@2x) so the iOS AppIcon
# (single 1024, ios platform) is untouched.
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon-mac
# App Sandbox + camera/files/network/keychain-access-groups.
CODE_SIGN_ENTITLEMENTS: graffito-mac.entitlements
# Hardened Runtime (audit M5). App Sandbox and Hardened Runtime cover
# different things: the sandbox limits what this process may reach,
# Hardened Runtime stops another process running as the same user from
# attaching a debugger or injecting a dylib INTO it. That matters here
# because the notes key is cached in memory for the whole session
# (there is no idle re-lock yet -- audit M4), so process memory is a
# standing target. Not required for the Mac App Store, but free: the
# app loads no third-party plug-ins and needs no JIT (femtovg renders
# through OpenGL), so none of the com.apple.security.cs.* relaxations
# are needed -- and none should be added without re-reading M5.
ENABLE_HARDENED_RUNTIME: YES
info:
path: Info-mac.plist
properties:
CFBundleDisplayName: Graffito
CFBundleName: Graffito
CFBundleExecutable: graffito
CFBundlePackageType: APPL
# Same trap as the iOS target above: without this entry xcodegen
# defaults CFBundleVersion to "1" on every generate — which is how
# the first org-account macOS upload went out as "build 1" while
# CURRENT_PROJECT_VERSION said 61. Track the shared setting so one
# bump moves both platforms.
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)"
NSCameraUsageDescription: "Scan QR codes (keys, addresses, PSBTs, sync bundles)."
NSHighResolutionCapable: true
ITSAppUsesNonExemptEncryption: false
# Mac App Store requires an app category; mirrors the iOS PRODUCTIVITY listing.
LSApplicationCategoryType: public.app-category.productivity
sources:
- Assets.xcassets
# Not enforced on macOS, but shipped for parity so the two platforms make
# the same privacy claims from one file (Contents/Resources here).
- PrivacyInfo.xcprivacy
postCompileScripts:
- name: Build Rust binary with cargo
script: |
bash "${SRCROOT}/build_mac.bash" graffito
outputFiles:
- $(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)