a native ios client for gitbay

client ios swift

https://gitbay.org

Commit 1a113f7129

1a113f7129bbfd9af56a4157275d50645e29fdda

parent: bb6e57f79e

Verified · cmc

cmc <hello@cleberg.net> · 2026-08-28T20:55:09Z

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.
gitbay.xcodeproj/project.pbxproj +2
@@ -415,6 +415,7 @@
415415 GENERATE_INFOPLIST_FILE = YES;
416416 INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
417417 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
418 INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
418419 INFOPLIST_KEY_UILaunchScreen_Generation = YES;
419420 INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
420421 INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
@@ -447,6 +448,7 @@
447448 GENERATE_INFOPLIST_FILE = YES;
448449 INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
449450 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
451 INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
450452 INFOPLIST_KEY_UILaunchScreen_Generation = YES;
451453 INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
452454 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 {
4646 ensureFixtureIssue()
4747 try requireFixtureBranch()
4848 }
49 if name.contains("testBlameAndEditFlows") {
50 try requireFixtureRepo()
51 }
4952 }
5053
5154 override func tearDownWithError() throws {
@@ -275,6 +278,21 @@ final class LiveSmokeUITests: XCTestCase {
275278 keys.tap()
276279 }
277280
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
278296 /// Scroll a list until an element is in the hierarchy. Offscreen
279297 /// rows do not exist to XCUITest, so waitForExistence alone fails on
280298 /// anything below the fold.