Commit 33a6a7e764
33a6a7e76499841d50aa2ff42c13898df38eb8d0
parent: 23ea243255
Unsigned
cmc <hello@cleberg.net> · 2026-08-28 20:55 UTC
release: privacy manifest, export compliance, and the edit fixture
The archive carried no PrivacyInfo.xcprivacy while SessionStore uses
UserDefaults, a required-reason API. App Store Connect refuses such
uploads (ITMS-91053). The manifest declares that one access with reason
CA92.1 and states what is true otherwise: no tracking, no collection,
no third-party SDK.
ITSAppUsesNonExemptEncryption = NO so uploads stop asking; the app uses
HTTPS and nothing else.
testBlameAndEditFlows wanted cmc/ui-smoke-edit, which did not exist —
the same missing-fixture failure as #8, in a test that was not failing
when I audited that issue. The repo is seeded with notes.txt, and setUp
skips with the reason if it goes missing, since seeding a first commit
is a push no test can make.
Layout: unified · split
gitbay.xcodeproj/project.pbxproj
+2
| @@ -415,6 +415,7 @@ |
| 415 | GENERATE_INFOPLIST_FILE = YES; |
415 | GENERATE_INFOPLIST_FILE = YES; |
| 416 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; |
416 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; |
| 417 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; |
417 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; |
| |
418 | INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; |
| 418 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; |
419 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; |
| 419 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
420 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
| 420 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
421 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
| @@ -447,6 +448,7 @@ |
| 447 | GENERATE_INFOPLIST_FILE = YES; |
448 | GENERATE_INFOPLIST_FILE = YES; |
| 448 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; |
449 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; |
| 449 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; |
450 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; |
| |
451 | INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; |
| 450 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; |
452 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; |
| 451 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
453 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
| 452 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
454 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; |
gitbay/PrivacyInfo.xcprivacy
added
+33
| @@ -0,0 +1,33 @@ |
| |
1 | <?xml version="1.0" encoding="UTF-8"?> |
| |
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| |
3 | <plist version="1.0"> |
| |
4 | <dict> |
| |
5 | <!-- No tracking: the app talks only to the gitbay instance the user |
| |
6 | names at sign-in, and to nothing else. --> |
| |
7 | <key>NSPrivacyTracking</key> |
| |
8 | <false/> |
| |
9 | <key>NSPrivacyTrackingDomains</key> |
| |
10 | <array/> |
| |
11 | |
| |
12 | <!-- Nothing is collected. The API token is held in the Keychain on |
| |
13 | the device and sent only to that instance; no analytics, no |
| |
14 | crash reporting, no third-party SDK. --> |
| |
15 | <key>NSPrivacyCollectedDataTypes</key> |
| |
16 | <array/> |
| |
17 | |
| |
18 | <key>NSPrivacyAccessedAPITypes</key> |
| |
19 | <array> |
| |
20 | <dict> |
| |
21 | <!-- SessionStore keeps which account is active across |
| |
22 | relaunches. App's own data, read and written by this |
| |
23 | app only. --> |
| |
24 | <key>NSPrivacyAccessedAPIType</key> |
| |
25 | <string>NSPrivacyAccessedAPICategoryUserDefaults</string> |
| |
26 | <key>NSPrivacyAccessedAPITypeReasons</key> |
| |
27 | <array> |
| |
28 | <string>CA92.1</string> |
| |
29 | </array> |
| |
30 | </dict> |
| |
31 | </array> |
| |
32 | </dict> |
| |
33 | </plist> |
gitbayUITests/LiveSmokeUITests.swift
+18
| @@ -46,6 +46,9 @@ final class LiveSmokeUITests: XCTestCase { |
| 46 | ensureFixtureIssue() |
46 | ensureFixtureIssue() |
| 47 | try requireFixtureBranch() |
47 | try requireFixtureBranch() |
| 48 | } |
48 | } |
| |
49 | if name.contains("testBlameAndEditFlows") { |
| |
50 | try requireFixtureRepo() |
| |
51 | } |
| 49 | } |
52 | } |
| 50 | |
53 | |
| 51 | override func tearDownWithError() throws { |
54 | override func tearDownWithError() throws { |
| @@ -275,6 +278,21 @@ final class LiveSmokeUITests: XCTestCase { |
| 275 | keys.tap() |
278 | keys.tap() |
| 276 | } |
279 | } |
| 277 | |
280 | |
| |
281 | /// The edit flow saves a change to a real file. Seeding a |
| |
282 | /// repository's first commit is a push, which no test can make, so |
| |
283 | /// this only checks — and says why, rather than failing later at |
| |
284 | /// "cmc/ui-smoke-edit not in the repo list". |
| |
285 | private func requireFixtureRepo() throws { |
| |
286 | guard let data = readCommand(["repo", "show", "cmc/ui-smoke-edit"]), |
| |
287 | let envelope = try? JSONSerialization.jsonObject(with: data) as? [String: Any] |
| |
288 | else { return } // no token, or the instance is unreachable |
| |
289 | try XCTSkipUnless(envelope["data"] != nil, """ |
| |
290 | cmc/ui-smoke-edit is missing. The edit flow saves a change to \ |
| |
291 | notes.txt in it; recreate the repo with that file (see its \ |
| |
292 | README) and run again. |
| |
293 | """) |
| |
294 | } |
| |
295 | |
| 278 | /// Scroll a list until an element is in the hierarchy. Offscreen |
296 | /// Scroll a list until an element is in the hierarchy. Offscreen |
| 279 | /// rows do not exist to XCUITest, so waitForExistence alone fails on |
297 | /// rows do not exist to XCUITest, so waitForExistence alone fails on |
| 280 | /// anything below the fold. |
298 | /// anything below the fold. |