From e00f33a0765ce601feabade0c09972753671a631 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tsisyk.com>
Date: Wed, 25 Dec 2024 20:15:11 +0000
Subject: [PATCH] [github] Manage private secrets with GitHub Secrets to
 enhance security

1. Restore the original simple version of `configure.sh`
   Restores 08e37f4 "Refactor configure.sh"
   Reverts b87ee95b "Fixed configure.sh script and gh actions"

2. Use GitHub Secrets instead of a private git repository to enhance
   security standards and ensure credentials are encrypted and safely
   managed.

3. Document credentials used by GitHub Actions in docs/CREDENTIALS.md

4. Include `network_security_config.xml` directly into the repo
   as it has nothing sensitive.

5. Include Apple WWDR intermediate certificates directly into the repo
   as they are not sensitive and publicly available.
   https://developer.apple.com/help/account/reference/wwdr-intermediate-certificates

6. Add `private.h` in the repository since it does not differ from
   `private_defaults.h`.

Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
---
 .github/workflows/android-beta.yaml           |  27 +--
 .github/workflows/android-check.yaml          |   8 +-
 .github/workflows/android-monkey.yaml         |  29 +--
 .../workflows/android-release-metadata.yaml   |  17 +-
 .github/workflows/android-release.yaml        |  29 +--
 .github/workflows/coverage-check.yaml         |   2 +-
 .github/workflows/ios-beta.yaml               |  27 +--
 .github/workflows/ios-check.yaml              |   2 +-
 .github/workflows/ios-release.yaml            |  17 +-
 .github/workflows/linux-check.yaml            |   4 +-
 .github/workflows/macos-check.yaml            |   2 +-
 android/app/build.gradle                      |  19 +-
 .../main/res/xml/network_security_config.xml  |  20 ++
 configure.sh                                  | 176 ++----------------
 docs/CREDENTIALS.md                           | 127 +++++++++++++
 private_default.h => private.h                |   5 +-
 xcode/fastlane/Fastfile                       |  10 +
 xcode/keys/Apple/AppleWWDRCAG2.cer            | Bin 0 -> 763 bytes
 xcode/keys/Apple/AppleWWDRCAG3.cer            | Bin 0 -> 1109 bytes
 xcode/keys/Apple/AppleWWDRCAG4.cer            | Bin 0 -> 1113 bytes
 xcode/keys/Apple/AppleWWDRCAG5.cer            | Bin 0 -> 1113 bytes
 xcode/keys/Apple/AppleWWDRCAG6.cer            | Bin 0 -> 794 bytes
 xcode/keys/Apple/AppleWWDRCAG7.cer            | Bin 0 -> 1113 bytes
 xcode/keys/Apple/AppleWWDRCAG8.cer            | Bin 0 -> 1113 bytes
 24 files changed, 273 insertions(+), 248 deletions(-)
 create mode 100644 android/app/src/main/res/xml/network_security_config.xml
 create mode 100644 docs/CREDENTIALS.md
 rename private_default.h => private.h (62%)
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG2.cer
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG3.cer
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG4.cer
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG5.cer
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG6.cer
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG7.cer
 create mode 100644 xcode/keys/Apple/AppleWWDRCAG8.cer

diff --git a/.github/workflows/android-beta.yaml b/.github/workflows/android-beta.yaml
index 1ca85c9e06..ae4b3ef480 100644
--- a/.github/workflows/android-beta.yaml
+++ b/.github/workflows/android-beta.yaml
@@ -56,19 +56,24 @@ jobs:
         shell: bash
         run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
 
-      - name: Checkout private keys
-        uses: actions/checkout@v4
-        with:
-          repository: ${{ secrets.PRIVATE_REPO }}
-          ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
-          ref: master
-          path: private.git
-
-      - name: Configure repo with private keys
+      - name: Restore beta keys
         shell: bash
         run: |
-          ./configure.sh ./private.git
-          rm -rf ./private.git
+          echo "$PRIVATE_H" | base64 -d > private.h
+          echo "$FIREBASE_APP_DISTRIBUTION_JSON" | base64 -d > android/app/firebase-app-distribution.json
+          echo "$GOOGLE_SERVICES_JSON" | base64 -d > android/app/google-services.json
+          echo "$SECURE_PROPERTIES" | base64 -d > android/app/secure.properties
+          echo "$RELEASE_KEYSTORE" | base64 -d > android/app/release.keystore
+        env:
+          PRIVATE_H: ${{ secrets.PRIVATE_H }}
+          FIREBASE_APP_DISTRIBUTION_JSON: ${{ secrets.FIREBASE_APP_DISTRIBUTION_JSON }}
+          GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
+          SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }}
+          RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
+
+      - name: Configure repository
+        shell: bash
+        run: ./configure.sh
 
       - name: Compile
         shell: bash
diff --git a/.github/workflows/android-check.yaml b/.github/workflows/android-check.yaml
index 7bb51d0acd..dcff58bab3 100644
--- a/.github/workflows/android-check.yaml
+++ b/.github/workflows/android-check.yaml
@@ -51,7 +51,7 @@ jobs:
         shell: bash
         run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
 
-      - name: Configure in Open Source mode
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
@@ -66,11 +66,11 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        flavor: [WebDebug, FdroidBeta]
+        flavor: [WebDebug, FdroidDebug]
         include:
           - flavor: WebDebug
             arch: arm64
-          - flavor: FdroidBeta
+          - flavor: FdroidDebug
             arch: arm32
     # Cancels previous jobs if the same branch or PR was updated again.
     concurrency:
@@ -93,7 +93,7 @@ jobs:
         shell: bash
         run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
 
-      - name: Configure in Open Source mode
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
diff --git a/.github/workflows/android-monkey.yaml b/.github/workflows/android-monkey.yaml
index c0da2212b1..c9b8f202c3 100644
--- a/.github/workflows/android-monkey.yaml
+++ b/.github/workflows/android-monkey.yaml
@@ -56,19 +56,26 @@ jobs:
         shell: bash
         run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
 
-      - name: Checkout private keys
-        uses: actions/checkout@v4
-        with:
-          repository: ${{ secrets.PRIVATE_REPO }}
-          ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
-          ref: master
-          path: private.git
-
-      - name: Configure repo with private keys
+      - name: Restore beta keys
         shell: bash
         run: |
-          ./configure.sh ./private.git
-          rm -rf ./private.git
+          echo "$PRIVATE_H" | base64 -d > private.h
+          echo "$FIREBASE_TEST_LAB_JSON" | base64 -d > android/app/firebase-test-lab.json
+          echo "$FIREBASE_APP_DISTRIBUTION_JSON" | base64 -d > android/app/firebase-app-distribution.json
+          echo "$GOOGLE_SERVICES_JSON" | base64 -d > android/app/google-services.json
+          echo "$SECURE_PROPERTIES" | base64 -d > android/app/secure.properties
+          echo "$RELEASE_KEYSTORE" | base64 -d > android/app/release.keystore
+        env:
+          PRIVATE_H: ${{ secrets.PRIVATE_H }}
+          FIREBASE_TEST_LAB_JSON: ${{ secrets.FIREBASE_TEST_LAB_JSON }}
+          FIREBASE_APP_DISTRIBUTION_JSON: ${{ secrets.FIREBASE_APP_DISTRIBUTION_JSON }}
+          GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
+          SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }}
+          RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
+
+      - name: Configure repository
+        shell: bash
+        run: ./configure.sh
 
       - name: Compile
         shell: bash
diff --git a/.github/workflows/android-release-metadata.yaml b/.github/workflows/android-release-metadata.yaml
index 004fd549f3..37fe9b59e2 100644
--- a/.github/workflows/android-release-metadata.yaml
+++ b/.github/workflows/android-release-metadata.yaml
@@ -26,19 +26,14 @@ jobs:
           ref: master
           path: screenshots
 
-      - name: Checkout private keys
-        uses: actions/checkout@v4
-        with:
-          repository: ${{ secrets.PRIVATE_REPO }}
-          ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
-          ref: master
-          path: private.git
-
-      - name: Configure repo with private keys
+      - name: Restore release keys
         shell: bash
         run: |
-          ./configure.sh ./private.git
-          rm -rf ./private.git
+          echo "$PRIVATE_H" | base64 -d > private.h
+          echo "$GOOGLE_PLAY_JSON" | base64 -d > android/app/google-play.json
+        env:
+          PRIVATE_H: ${{ secrets.PRIVATE_H }}
+          GOOGLE_PLAY_JSON: ${{ secrets.GOOGLE_PLAY_JSON }}
 
       - name: Upload
         shell: bash
diff --git a/.github/workflows/android-release.yaml b/.github/workflows/android-release.yaml
index ff18d4b74a..db205b7f51 100644
--- a/.github/workflows/android-release.yaml
+++ b/.github/workflows/android-release.yaml
@@ -100,19 +100,26 @@ jobs:
           ref: master
           path: screenshots
 
-      - name: Checkout private keys
-        uses: actions/checkout@v4
-        with:
-          repository: ${{ secrets.PRIVATE_REPO }}
-          ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
-          ref: master
-          path: private.git
-
-      - name: Configure repo with private keys
+      - name: Restore release keys
         shell: bash
         run: |
-          ./configure.sh ./private.git
-          rm -rf ./private.git
+          echo "$PRIVATE_H" | base64 -d > private.h
+          echo "$GOOGLE_PLAY_JSON" | base64 -d > android/app/google-play.json
+          echo "$HUAWEI_APPGALLERY_JSON" | base64 -d > android/app/huawei-appgallery.json
+          echo "$AGCONNECT_SERVICES_JSON" | base64 -d > android/app/agconnect-services.json
+          echo "$SECURE_PROPERTIES" | base64 -d > android/app/secure.properties
+          echo "$RELEASE_KEYSTORE" | base64 -d > android/app/release.keystore
+        env:
+          PRIVATE_H: ${{ secrets.PRIVATE_H }}
+          GOOGLE_PLAY_JSON: ${{ secrets.GOOGLE_PLAY_JSON }}
+          HUAWEI_APPGALLERY_JSON: ${{ secrets.HUAWEI_APPGALLERY_JSON }}
+          AGCONNECT_SERVICES_JSON: ${{ secrets.AGCONNECT_SERVICES_JSON }}
+          SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }}
+          RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
+
+      - name: Configure repository
+        shell: bash
+        run: ./configure.sh
 
       - name: Set up SDK
         shell: bash
diff --git a/.github/workflows/coverage-check.yaml b/.github/workflows/coverage-check.yaml
index d5e82ff6d1..833b5180fa 100644
--- a/.github/workflows/coverage-check.yaml
+++ b/.github/workflows/coverage-check.yaml
@@ -94,7 +94,7 @@ jobs:
               llvm \
               gcovr
 
-      - name: Configure
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
diff --git a/.github/workflows/ios-beta.yaml b/.github/workflows/ios-beta.yaml
index 321142ccc5..5699ce0e3e 100644
--- a/.github/workflows/ios-beta.yaml
+++ b/.github/workflows/ios-beta.yaml
@@ -52,18 +52,23 @@ jobs:
       - name: Parallel submodules checkout
         run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20))
 
-      - name: Checkout private keys
-        uses: actions/checkout@v4
-        with:
-          repository: ${{ secrets.PRIVATE_REPO }}
-          ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
-          ref: master
-          path: private.git
-
-      - name: Configure repo with private keys
+      - name: Restore beta keys
+        shell: bash
         run: |
-          ./configure.sh ./private.git
-          rm -rf ./private.git
+          mkdir -p xcode/keys
+          echo "$PRIVATE_H" | base64 -d > private.h
+          echo "$APPSTORE_JSON" | base64 -d > xcode/keys/appstore.json
+          echo "$CERTIFICATES_DEV_P12" | base64 -d > xcode/keys/CertificatesDev.p12
+          echo "$CERTIFICATES_DISTR_P12" | base64 -d > xcode/keys/CertificatesDistr.p12
+        env:
+          PRIVATE_H: ${{ secrets.PRIVATE_H }}
+          APPSTORE_JSON: ${{ secrets.APPSTORE_JSON }}
+          CERTIFICATES_DEV_P12: ${{ secrets.CERTIFICATES_DEV_P12 }}
+          CERTIFICATES_DISTR_P12: ${{ secrets.CERTIFICATES_DISTR_P12 }}
+
+      - name: Configure repository
+        shell: bash
+        run: ./configure.sh
 
       - name: Compile and upload to TestFlight
         run: |
diff --git a/.github/workflows/ios-check.yaml b/.github/workflows/ios-check.yaml
index d91674f209..db9af68c19 100644
--- a/.github/workflows/ios-check.yaml
+++ b/.github/workflows/ios-check.yaml
@@ -59,7 +59,7 @@ jobs:
         shell: bash
         run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20))
 
-      - name: Configure
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
diff --git a/.github/workflows/ios-release.yaml b/.github/workflows/ios-release.yaml
index 6b698a53d8..7a94b16fe7 100644
--- a/.github/workflows/ios-release.yaml
+++ b/.github/workflows/ios-release.yaml
@@ -16,20 +16,13 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v4
 
-      - name: Checkout private keys
-        uses: actions/checkout@v4
-        with:
-          repository: ${{ secrets.PRIVATE_REPO }}
-          ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
-          ref: master
-          path: ./private.git
-
-      - name: Configure repo with private keys
+      - name: Restore release keys
         shell: bash
         run: |
-          mkdir -p xcode/keys/
-          cp -p ./private.git/xcode/keys/appstore.json xcode/keys/
-          rm -rf ./private.git
+          mkdir -p xcode/keys
+          echo "$APPSTORE_JSON" | base64 -d > xcode/keys/appstore.json
+        env:
+          APPSTORE_JSON: ${{ secrets.APPSTORE_JSON }}
 
       - name: Checkout screenshots
         uses: actions/checkout@v4
diff --git a/.github/workflows/linux-check.yaml b/.github/workflows/linux-check.yaml
index 805e7aebf0..17adeecbd2 100644
--- a/.github/workflows/linux-check.yaml
+++ b/.github/workflows/linux-check.yaml
@@ -67,7 +67,7 @@ jobs:
               libqt6positioning6-plugins \
               libqt6positioning6
 
-      - name: Configure
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
@@ -134,7 +134,7 @@ jobs:
               libqt6positioning6-plugins \
               libqt6positioning6
 
-      - name: Configure
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
diff --git a/.github/workflows/macos-check.yaml b/.github/workflows/macos-check.yaml
index caacce95c4..3d6c5232e0 100644
--- a/.github/workflows/macos-check.yaml
+++ b/.github/workflows/macos-check.yaml
@@ -57,7 +57,7 @@ jobs:
         run: |
           HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install ninja qt@6
 
-      - name: Configure
+      - name: Configure repository
         shell: bash
         run: ./configure.sh
 
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 0e60b8e807..e710eb6550 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -45,7 +45,6 @@ repositories {
 }
 
 apply plugin: 'com.android.application'
-apply from: 'secure.properties'
 if (googleFirebaseServicesEnabled) {
   apply plugin: 'com.google.gms.google-services'
   apply plugin: 'com.google.firebase.crashlytics'
@@ -247,6 +246,11 @@ android {
     }
   }
 
+  def securityPropertiesFileExists = file('secure.properties').exists()
+  if (securityPropertiesFileExists) {
+    apply from: 'secure.properties'
+  }
+
   signingConfigs {
     debug {
       storeFile file('debug.keystore')
@@ -256,10 +260,15 @@ android {
     }
 
     release {
-      storeFile file(spropStoreFile)
-      storePassword spropStorePassword
-      keyAlias spropKeyAlias
-      keyPassword spropKeyPassword
+      if (securityPropertiesFileExists) {
+        println('The release signing keys are available')
+        storeFile file(spropStoreFile)
+        storePassword spropStorePassword
+        keyAlias spropKeyAlias
+        keyPassword spropKeyPassword
+      } else {
+        println('The release signing keys are unavailable')
+      }
     }
   }
 
diff --git a/android/app/src/main/res/xml/network_security_config.xml b/android/app/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000000..768520426e
--- /dev/null
+++ b/android/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <base-config cleartextTrafficPermitted="true">
+    <trust-anchors>
+      <!-- Certificates are required for Android 7 and below. See the link for details:
+           https://community.letsencrypt.org/t/letsencrypt-certificates-fails-on-android-phones-running-android-7-or-older/205686 -->
+      <certificates src="@raw/isrgrootx1" />
+      <certificates src="@raw/globalsignr4" />
+      <certificates src="@raw/gtsrootr1" />
+      <certificates src="@raw/gtsrootr2" />
+      <certificates src="@raw/gtsrootr3" />
+      <certificates src="@raw/gtsrootr4" />
+      <certificates src="system" />
+    </trust-anchors>
+  </base-config>
+  <domain-config cleartextTrafficPermitted="true">
+    <domain includeSubdomains="true">organicmaps.app</domain>
+    <domain includeSubdomains="true">omaps.app</domain>
+  </domain-config>
+</network-security-config>
diff --git a/configure.sh b/configure.sh
index 7b1eeeb6fd..77b55242ad 100755
--- a/configure.sh
+++ b/configure.sh
@@ -1,171 +1,17 @@
 #!/usr/bin/env bash
+#
 # Please run this script to configure the repository after cloning it.
+#
 
-# When configuring with private repository, the following override hierarchy is used:
-# - commandline parameters - most specific, always wins.
-# - stdin parameters.
-# - saved repository - least specific, if present.
-# - fallback to opensource mode.
+set -euo pipefail
 
-# Stop on the first error.
-set -e -u
+echo "Configuring the repository for development."
 
-BASE_PATH=$(cd "$(dirname "$0")"; pwd)
-
-DEFAULT_PRIVATE_HEADER="$BASE_PATH/private_default.h"
-PRIVATE_HEADER="private.h"
-PRIVATE_PROPERTIES="android/app/secure.properties"
-PRIVATE_NETWORK_CONFIG="android/app/src/main/res/xml/network_security_config.xml"
-PRIVATE_GOOGLE_SERVICES="android/app/google-services.json"
-
-SAVED_PRIVATE_REPO_FILE="$BASE_PATH/.private_repository_url"
-SAVED_PRIVATE_BRANCH_FILE="$BASE_PATH/.private_repository_branch"
-TMP_REPO_DIR="$BASE_PATH/.tmp.private.repo"
-
-usage() {
-  echo "This tool configures Organic Maps for an opensource build by default"
-  echo "and bootstraps the Boost submodule after that."
-  echo
-  echo "To e.g. publish in app stores populate following configs with your own private keys etc."
-  echo "  $PRIVATE_HEADER"
-  echo "  $PRIVATE_PROPERTIES"
-  echo "  $PRIVATE_NETWORK_CONFIG"
-  echo "  $PRIVATE_GOOGLE_SERVICES"
-  echo "The tool can copy over the necessary configs from a given private repo and a branch"
-  echo "(it copies all files except README.md)."
-  echo "It remembers the repo and the branch to pull the config changes automatically on next run."
-  echo
-  echo "Usage:"
-  echo "  $0 private_repo_url [private_repo_branch]  - copy configs from a private repo (master is the default branch)"
-  echo "  echo 'private_repo_url [private_repo_branch]' | $0  - alternate invocation for private repo configuration"
-  echo "  $0  - use a saved repo and a branch if present or default to an opensource build configs"
-  echo ""
-}
-
-setup_opensource() {
-  echo "Initializing repository with default values in Open-Source mode."
-  cat "$DEFAULT_PRIVATE_HEADER" > "$BASE_PATH/$PRIVATE_HEADER"
-  echo 'ext {
-  spropStoreFile = "debug.keystore"
-  spropStorePassword = "12345678"
-  spropKeyAlias = "debug"
-  spropKeyPassword = "12345678"
-}
-' > "$BASE_PATH/$PRIVATE_PROPERTIES"
-  echo '<?xml version="1.0" encoding="utf-8"?>
-<network-security-config>
-  <base-config>
-    <trust-anchors>
-      <!-- Certificates are required for Android 7 and below. See the link for details:
-           https://community.letsencrypt.org/t/letsencrypt-certificates-fails-on-android-phones-running-android-7-or-older/205686 -->
-      <certificates src="@raw/isrgrootx1" />
-      <certificates src="@raw/globalsignr4" />
-      <certificates src="@raw/gtsrootr1" />
-      <certificates src="@raw/gtsrootr2" />
-      <certificates src="@raw/gtsrootr3" />
-      <certificates src="@raw/gtsrootr4" />
-      <certificates src="system" />
-    </trust-anchors>
-  </base-config>
-</network-security-config>
-' > "$BASE_PATH/$PRIVATE_NETWORK_CONFIG"
-  rm -f "$BASE_PATH/$PRIVATE_GOOGLE_SERVICES"
-}
-
-# Clone the private repo and copy all of its files (except README.md) into the main repo
-setup_private() {
-  echo "Copying private configuration files from the repo '$PRIVATE_REPO', branch '$PRIVATE_BRANCH'"
-  set -x
-  rm -rf "$TMP_REPO_DIR"
-  git clone --branch "$PRIVATE_BRANCH" --depth 1 "$PRIVATE_REPO" "$TMP_REPO_DIR"
-  echo "$PRIVATE_REPO" > "$SAVED_PRIVATE_REPO_FILE"
-  echo "$PRIVATE_BRANCH" > "$SAVED_PRIVATE_BRANCH_FILE"
-  echo "Saved private repository url '$PRIVATE_REPO' to '$SAVED_PRIVATE_REPO_FILE'"
-  echo "Saved private branch '$PRIVATE_BRANCH' to '$SAVED_PRIVATE_BRANCH_FILE'"
-  cd $TMP_REPO_DIR
-  rm -rf "$TMP_REPO_DIR/.git" "$TMP_REPO_DIR/README.md"
-  cp -Rv "$TMP_REPO_DIR"/* "$BASE_PATH"
-  rm -rf "$TMP_REPO_DIR"
-  # Remove old android secrets during the transition period to the new project structure
-  echo "Removing keys from old locations"
-  rm -f android/release.keystore \
-        android/secure.properties \
-        android/libnotify.properties \
-        android/google-services.json \
-        android/google-play.json \
-        android/firebase-app-distribution.json \
-        android/firebase-test-lab.json \
-        android/huawei-appgallery.json \
-        android/res/xml/network_security_config.xml
-  set +x
-  echo "Private files have been updated."
-}
-
-if [ "${1-}" = "-h" -o "${1-}" = "--help" ]; then
-  usage
-  exit 1
+if [ ! -d 3party/boost/tools ]; then
+  git submodule update --init --recursive
 fi
-
-ARGS_PRIVATE_REPO=${1-}
-ARGS_PRIVATE_BRANCH=${2-}
-
-if [ -n "$ARGS_PRIVATE_REPO" ]; then
-  PRIVATE_REPO=$ARGS_PRIVATE_REPO
-  if [ -n "$ARGS_PRIVATE_BRANCH" ]; then
-    PRIVATE_BRANCH=$ARGS_PRIVATE_BRANCH
-  else
-    PRIVATE_BRANCH=master
-  fi
-else
-  read -t 1 READ_PRIVATE_REPO READ_PRIVATE_BRANCH || true
-  if [ -n "${READ_PRIVATE_REPO-}" ]; then
-    PRIVATE_REPO=$READ_PRIVATE_REPO
-    if [ -n "${READ_PRIVATE_BRANCH-}" ]; then
-      PRIVATE_BRANCH=$READ_PRIVATE_BRANCH
-    else
-      PRIVATE_BRANCH=master
-    fi
-  elif [ -f "$SAVED_PRIVATE_REPO_FILE" ]; then
-    PRIVATE_REPO=`cat "$SAVED_PRIVATE_REPO_FILE"`
-    echo "Using stored private repository URL: $PRIVATE_REPO"
-    if [ -f "$SAVED_PRIVATE_BRANCH_FILE" ]; then
-      PRIVATE_BRANCH=`cat "$SAVED_PRIVATE_BRANCH_FILE"`
-      echo "Using stored private branch: $PRIVATE_BRANCH"
-    else
-      PRIVATE_BRANCH=master
-    fi
-  else
-    PRIVATE_REPO=""
-  fi
-fi
-
-if [ -n "$PRIVATE_REPO" ]; then
-  setup_private
-else
-  setup_opensource
-fi
-
-# TODO: Remove these lines when XCode project is finally generated by CMake.
-if [ ! -d "$BASE_PATH/3party/boost/" ]; then
-  echo "You need to have Boost submodule present to run bootstrap.sh"
-  echo "Try 'git submodule update --init --recursive'"
-  exit 1
-fi
-if [ ! -d "$BASE_PATH/3party/boost/tools" ]; then
-  echo "Boost's submodule 'tools' is missing, it is required for bootstrap"
-  echo "Try 'git submodule update --init --recursive'"
-  exit 1
-fi
-
-cd "$BASE_PATH/3party/boost/"
-if [[ "$OSTYPE" == msys ]]; then
-  echo "For Windows please run:"
-  echo "cd 3party\\boost"
-  echo "bootstrap.bat"
-  echo "b2 headers"
-  echo "cd ..\\.."
-else
-  ./bootstrap.sh
-  ./b2 headers
-fi
-cd "$BASE_PATH"
+pushd 3party/boost/
+./bootstrap.sh
+./b2 headers
+popd
+echo "The repository is configured for development."
diff --git a/docs/CREDENTIALS.md b/docs/CREDENTIALS.md
new file mode 100644
index 0000000000..f232113191
--- /dev/null
+++ b/docs/CREDENTIALS.md
@@ -0,0 +1,127 @@
+This file contains a list of all sensitive credentials, access keys, authentication tokens, and security certificates used by CI/CD (Github Actions).
+
+- [PRIVATE\_H](#private_h)
+- [RELEASE\_KEYSTORE](#release_keystore)
+- [SECURE\_PROPERTIES](#secure_properties)
+- [FIREBASE\_APP\_DISTRIBUTION\_JSON](#firebase_app_distribution_json)
+- [FIREBASE\_TEST\_LAB\_JSON](#firebase_test_lab_json)
+- [GOOGLE\_SERVICES\_JSON](#google_services_json)
+- [GOOGLE\_PLAY\_JSON](#google_play_json)
+- [HUAWEI\_APPGALLERY\_JSON](#huawei_appgallery_json)
+- [AGCONNECT\_SERVICES\_JSON](#agconnect_services_json)
+- [APPSTORE\_JSON](#appstore_json)
+- [CERTIFICATES\_DEV\_P12](#certificates_dev_p12)
+- [CERTIFICATES\_DISTR\_P12](#certificates_distr_p12)
+- [APPSTORE\_CERTIFICATE\_PASSWORD](#appstore_certificate_password)
+
+## PRIVATE_H
+
+Shared compile-time secrets for all platforms.
+
+```bash
+gh secret set PRIVATE_H --env beta --body "$(base64 < private.h)"
+gh secret set PRIVATE_H --env production --body "$(base64 < private.h)"
+```
+
+## RELEASE_KEYSTORE
+
+Android Java-compatible keystore with certificates used for signing APKs.
+
+```bash
+gh secret set RELEASE_KEYSTORE --env beta --body "$(base64 < android/app/release.keystore)"
+gh secret set RELEASE_KEYSTORE --env production --body "$(base64 < android/app/release.keystore)"
+```
+
+## SECURE_PROPERTIES
+
+Android Gradle configuration file containing the passwords for the `release.keystore`.
+
+```bash
+gh secret set SECURE_PROPERTIES --env beta --body "$(base64 < android/app/secure.properties)"
+gh secret set SECURE_PROPERTIES --env production --body "$(base64 < android/app/secure.properties)"
+```
+
+## FIREBASE_APP_DISTRIBUTION_JSON
+
+Credentials for uploading betas to Google Firebase App Distribution.
+
+```bash
+gh secret set FIREBASE_APP_DISTRIBUTION_JSON --env beta --body "$(base64 < android/app/firebase-app-distribution.json)"
+```
+
+## FIREBASE_TEST_LAB_JSON
+
+Credentials for using Firebase Test Lab ("Monkey").
+
+```bash
+gh secret set FIREBASE_TEST_LAB_JSON --env beta --body "$(base64 < android/app/firebase-test-lab.json)"
+```
+
+## GOOGLE_SERVICES_JSON
+
+Credentials for using Firebase Crashlytics.
+
+```bash
+gh secret set GOOGLE_SERVICES_JSON --env beta --body "$(base64 < android/app/google-services.json)"
+```
+
+## GOOGLE_PLAY_JSON
+
+Credentials for uploading Android releases to Google Play.
+
+```bash
+gh secret set GOOGLE_PLAY_JSON --env production --body "$(base64 < android/app/google-play.json)"
+```
+
+## HUAWEI_APPGALLERY_JSON
+
+Credentials for uploading Android releases to Huawei AppGallery.
+
+```bash
+gh secret set HUAWEI_APPGALLERY_JSON --env production --body "$(base64 < android/app/huawei-appgallery.json)"
+```
+
+## AGCONNECT_SERVICES_JSON
+
+Credentials for Huawei Mobile Services (HMS) to use Location Kit (not yet finished).
+
+```bash
+gh secret set AGCONNECT_SERVICES_JSON --env beta --body "$(base64 < android/app/agconnect-services.json)"
+gh secret set AGCONNECT_SERVICES_JSON --env production --body "$(base64 < android/app/agconnect-services.json)"
+```
+
+## APPSTORE_JSON
+
+Credentials for uploading iOS releases to Apple AppStore Connect.
+
+```bash
+gh secret set APPSTORE_JSON --env beta --body "$(base64 < xcode/keys/appstore.json)"
+gh secret set APPSTORE_JSON --env production --body "$(base64 < xcode/keys/appstore.json)"
+```
+
+## CERTIFICATES_DEV_P12
+
+Credentials for signing iOS releases - dev keys.
+
+```bash
+gh secret set CERTIFICATES_DEV_P12 --env beta --body "$(base64 < xcode/keys/CertificatesDev.p12)"
+gh secret set CERTIFICATES_DEV_P12 --env production --body "$(base64 < xcode/keys/CertificatesDev.p12)"
+```
+
+## CERTIFICATES_DISTR_P12
+
+Credentials for signing iOS releases - AppStore keys.
+
+```bash
+gh secret set CERTIFICATES_DISTR_P12 --env beta --body "$(base64 < xcode/keys/CertificatesDistr.p12)"
+gh secret set CERTIFICATES_DISTR_P12 --env production --body "$(base64 < xcode/keys/CertificatesDistr.p12)"
+```
+
+## APPSTORE_CERTIFICATE_PASSWORD
+
+Password for `CertificatesDistr.p12`.
+
+```bash
+gh secret set APPSTORE_CERTIFICATE_PASSWORD --env beta
+gh secret set APPSTORE_CERTIFICATE_PASSWORD --env production
+```
diff --git a/private_default.h b/private.h
similarity index 62%
rename from private_default.h
rename to private.h
index fe417a1251..d5c7fba067 100644
--- a/private_default.h
+++ b/private.h
@@ -9,8 +9,9 @@
 #define MWM_GEOLOCATION_SERVER ""
 #define METASERVER_URL "https://meta.omaps.app/maps"
 #define DIFF_LIST_URL ""
-#define DEFAULT_URLS_JSON "[ \"https://cdn.organicmaps.app/\" ]"
-#define DEFAULT_CONNECTION_CHECK_IP "140.82.121.4"  // For now the IP of cdn.organicmaps.app
+#define DEFAULT_URLS_JSON "[ \"https://cdn-de1.organicmaps.app/\",\"https://cdn-us3.organicmaps.app/\",\"https://cdn-nl1.organicmaps.app/\",\"https://cdn-uk1.organicmaps.app/\",\"https://cdn-fi1.organicmaps.app/\",\"https://cdn.organicmaps.app/\" ]"
+#define DEFAULT_CONNECTION_CHECK_IP "65.108.198.117"  // For now the IP of cdn.organicmaps.app
 #define TRAFFIC_DATA_BASE_URL ""
 #define USER_BINDING_PKCS12 ""
 #define USER_BINDING_PKCS12_PASSWORD ""
+#define KAYAK_AFFILIATE_ID "kan_267335"
diff --git a/xcode/fastlane/Fastfile b/xcode/fastlane/Fastfile
index 36c796e575..5e7c4aa828 100644
--- a/xcode/fastlane/Fastfile
+++ b/xcode/fastlane/Fastfile
@@ -35,6 +35,16 @@ platform :ios do
         keychain_name: ENV['MATCH_KEYCHAIN_NAME'],
         keychain_password: ENV['MATCH_KEYCHAIN_PASSWORD']
       )
+      import_certificate(
+        certificate_path: 'keys/Apple/AppleWWDRCAG7.cer',
+        keychain_name: ENV['MATCH_KEYCHAIN_NAME'],
+        keychain_password: ENV['MATCH_KEYCHAIN_PASSWORD']
+      )
+      import_certificate(
+        certificate_path: 'keys/Apple/AppleWWDRCAG8.cer',
+        keychain_name: ENV['MATCH_KEYCHAIN_NAME'],
+        keychain_password: ENV['MATCH_KEYCHAIN_PASSWORD']
+      )
       # Organic Maps certificates.
       import_certificate(
         certificate_path: 'keys/CertificatesDev.p12',
diff --git a/xcode/keys/Apple/AppleWWDRCAG2.cer b/xcode/keys/Apple/AppleWWDRCAG2.cer
new file mode 100644
index 0000000000000000000000000000000000000000..b77e1e9eb6eea7cf06c82cb37dc6134902970659
GIT binary patch
literal 763
zcmXqLV)|~-#8k6@nTe5!i6j60jjt~kFMnsi#m1r4=5fxJg_+49-B8*<l8rf(g_%dl
zv7jI)RUs%pzeK^=Q9)P1-PlmgKm{bp%_9qubWSZQ$xO>kPAtjH&r@(LEy>6)$}Fig
z6gCh9spI0|f~fP%OV%^wHsAyavI#SV1{=tU^BS5Mm>QTF8JidznM8^68d)N74H_GO
z(nb)MXhRGM&o9bJDbGwvRd7iyOU=nING(zbO3eY=T?}=i5fz;nX&}tT4h|V6MraT*
zGqN)~F|geIu$|5O{M}*};UmtS%##~_$9*eV>y#K2!K4-}c_LYfoiix$)RCLv?{n2M
zx=SYZ9QoOhq49?^<AcDhmlyO-N-b{uZqWF}z>SSVn~jl`m7S51#md0KzzoJWU~JRM
zC@Cqh($~*VE-uhZ1jU42a(*tDYha=a7AOM7Ombqnv4Jcwm}L1_#8^aHwzZtGYD+2-
zi=6U8YVlr=`&Re44fsLQ!i<dnSy&C2fs}zfNI;oI!a%G+WcP-93nPp>W-aNOd2ip|
z*XwVcR#|Oe4pJb`Vql<WptC@0fkvAe)HTUPIY^E{afKdG&VUc3kso9gFflQ*83?d(
z0Ryn@dvXdJ6F&<RD+6+3W6oqSNMkZ&xViDT;W6cJ{=OG(x*x5T$P{cZRKJ|D_QCAb
zS^IMC+q*5Bz_~APp|#G2z)nY-_DlPLTK=R2b$Z*x?$4Gv)Hy@HXx-M?tE9M<L&`&5
ch&nGiDs*dlKygjng}hBMNdeabKUzfr0Po=NqW}N^

literal 0
HcmV?d00001

diff --git a/xcode/keys/Apple/AppleWWDRCAG3.cer b/xcode/keys/Apple/AppleWWDRCAG3.cer
new file mode 100644
index 0000000000000000000000000000000000000000..32f96f81dd6ea4c1c0f8e84698a50df773444b83
GIT binary patch
literal 1109
zcmXqLVhJ>8Vzyks%*4pVBv7+HlS_5G<-h9LE>#CBj=nSCW#iOp^Jx3d%gD&h%3zRW
z$Zf#M#vIDRCd?EXY$$9X2;y)Fb2%0i<fJNi<|XSHsu`$&1i6J}A%f1SMJ1VOnaPPI
znfZANj-@3T`9+x}m4;#lA|Q3l!n_c5LHYS53eJuOa^k#31_nlkmWCFF#wO-b;=IN{
zE>H*zq6|t6T@0MSI(e)iI>Ymea#G4OQ&JUNQp-|v@(WUn6oOK7z!nxO;Ibd;6K)<R
zcVoCuc#wU9>{o*(MkVCXU}R-rZerwT0E%-lH8C<W-1yr0XGJ7;`*EL%db(i~E?3Ad
zF?hMu<2|?Ye%+SeDzUE8PhUrx3B`n@%*#pA-EwUDsWUd;uCY!0^OR|sOxBjltLdlL
zytHQ*eAu$bT{f-Ha?y(|o^P!#Jrqc&>YLni>cB0Y1I-s6|D1SjdC!T1#gEpxT}+xg
zX~l#D^V*DQXL}#~nf<F`_v7mIy5e`E|20G^mx}KYI`~%lsmZy2N?Yf7Zg?8HzrSUX
z&5B(|+op;=VK_OT`NEmaR$|rHSYzhCc3;Q4Rkw#P)7RmGw~sZ;yk5nPYxJB$49*?w
zYMU~{`+gR${lDKb>!ynzs^Bts5HBBM?YUi*LCU=8QrPsRL7p`U7PH?oF*7nSE^d5p
z(D=qc2pB!G!i<dnSvU;XfD{uWgMmCqOqoT(K&(MT`$DGslrqkLU$T4k9F~1|_pRrM
zGjL(!&}L&~Wo2h%WU(+XGcbYi4H(-rGD=Dctn~HslZy-V5<zKAFF8LK%r!991q&1b
zlTUJ@fgZ>jc@}j8RRiS(iVNi1WT9G<i*k^3f>i4Pg$!gt>iJm2SVTDg9T1)HbA1Ze
zB%z&Z8p%A<-z?u`zz34%2l<2rm_yhM1lYL1`5`%ljfs(k3792Na|kd^Ffy!76@KyU
zL1VcKle^Qt_@$N#uaZ{&Jv!lJvGCP-voEaT@9jPPmhpU!hC}r6P!-1?f6gD=s{HcK
zn~(XY8f4249ZB?5O<&J{%2IXh<;PWLj5T=q^cIFY6#se_vyLrL^X=nS9{<EUMq=IN
z7hF!o7BL&T%~?0wLF(6+2bb-B>G!0~pME4H^8F=`FYGft6Cx##-<@*tz`>mQ3dQ$4
zudQ=tHhBjnSZuXy%6$`L7`%^vqK~I%N&m9I(=G0PvZd;Idw*Vv`CNY}hnv&vQOc7;
z=FB3JS6^jKS+(-^zi+cR(!1Yl?^q@7*}VSz={+ycznWUOVT<dcGf&%BaUFKFs*Jf6
JU@~{AH2}Gqoj3ph

literal 0
HcmV?d00001

diff --git a/xcode/keys/Apple/AppleWWDRCAG4.cer b/xcode/keys/Apple/AppleWWDRCAG4.cer
new file mode 100644
index 0000000000000000000000000000000000000000..b9f0bf298d3bc184ccd6e64f1482e6786d558bf5
GIT binary patch
literal 1113
zcmXqLVhJ^9Vzynt%*4pVBqDsLd}>hPQ`=)kFV6gbs`&ZL(Q}s!c-c6$+C196^D;7W
zvoaVY8FCwNvN4CUun9AT1{(?+2!c3V!d#981v#k-o_Wc7hH3^XAVF?nS%{!>YEemM
zT4r)$NoIbYf@5h(Mt)IdNu{Bffe1()voJ42T~L00iGs7Eft)z6k%6I+p_!qjv6+EM
zlsK<3h-&}=Q3j=kE(T6uojleMo#FXKIVt6tDX9uBsb#4-`30#(3PGtkU<->CaM=&_
z2{#Xuy9wMUJjgyl_Nze?qY`pxFtRc*H!<=v0L8hOniv@wF34A`s!})F;1>T}yzIt;
zxqO;^Yi*5|9?3R8`NVNz*7nN6SRNCWgwpTpocrC6w8?S2*niD3NMA1fPvOU=T$?(!
zpt89-d#*aa+_+_rgH=UfY~VuGhx>9S&dpYglyJPt-<#{GW$C5(V8VPqVgCy~vy66J
z&zdBsnzh8}oRVZKYr-8SuTN30%PW~`4@?iqnbcRt_{^>U=`*e0i#Dv4Set9yYN6cy
zs%zTY`RmgB7xOr%=T5zl)N#{UQ~mGTCHsT*CWxlm+|)}-F_z8Ay4$C?YDv84F@v}9
z&w9)zP1%0Ol8NDWO3xLZ#!vQFO{TY(svXK-$DFLlQ+-8xW71KkIeY)EXJTe#U|ihz
z-k|Y~fe<iyWQ7?S|FduyumLG1Mg{|UkeD)ygn?Lti1vj{_bFwZ|Gs4R>Nza??(SR9
z5oh4S#-Yu|$jZvj$jD-00E~GU-+-}ABcr6Gz)D{~Ke@O-FA<d1^pf*)!CV7lU9dnA
zF!>}W8t8$nk!MjiP&H6qptwN3O%|#(xhMxoCrGs(P{=?Qq@IsOj722+<}cajv!u8e
z&n#04XtSGmBD#Eq0Ut=3ALJ7jU@l=Z5Mbj1=ZEAJHYP?ECSaC8%^|=v!N_1AW;^fc
zw!@XrTop3*?l11v5t_&JcwK{14~yL4pc4fRD}J9_zTv8qOA~XGKieN`Pm$j@N`hL~
zFQ2RUoKc8*{#l2J3yjzI8#QYOM`+l*n=?P8%r-^+SY5BIg|F_q#%DX1?wHd#<@@~O
z?MnmGOr$LfEma=3r@vpiF{8TYo$dE^+o~U3`hP$1SXQa$R3(=cEPtl#;MTJg^c1@I
zwDDCWgMYM5l-aE+rD9Ib%(Dk-UOiIzH^XJekN2Aj?WJO`#MT-6&XHBw$M9hSbHq$X
zTf?X%hxL{#0-YzVW?3=kkncwCORH<V;$P3T-s9ilz$W~Ef_N8)yXK3e8JbJ|1z9t#
I&VQN@043;*)Bpeg

literal 0
HcmV?d00001

diff --git a/xcode/keys/Apple/AppleWWDRCAG5.cer b/xcode/keys/Apple/AppleWWDRCAG5.cer
new file mode 100644
index 0000000000000000000000000000000000000000..8b564c76803ca8f835222614eb2e6e7f1a109528
GIT binary patch
literal 1113
zcmXqLVhJ^9Vzynt%*4pVBw}6H!1eAj)52$OZco2?YK_L6kC{^pc-c6$+C196^D;7W
zvoaVY8FCwNvN4CUun9AT1{(?+2!c3V!d#981v#k-o_Wc7hH3^XAVF?nS%{!>YEemM
zT4r)$NoIbYf@5h(Mt)IdNu{Bffe1()voJ42T~L00iGs7Eft)z6k%6I+p_!qjv4yEw
zlsK<3h-&}=Q3j=kE(T6uojleMo#FXKIVt6tDX9uBsb#4-`30#(3PGtkU<->CaM=&_
z2{#XuyD8i!Jjgyl_Nze?qY`pxFtRc*H!<=v0L8hOniv@w=EvTW|NU#v1#cyr<JZ)F
ziGTkxU(PN?Fm2ZRxP7Zl_O8-V%)2HxMX^<<<RG6w;wqbDuR5>CCrYoKKQxEKqdIG+
z=Ejq0e@}FYUEIWC)3mE0=h1(zqStHwS?7D~o7XMqJGFLG^#pw;8NWZC`>yA2_1{-<
z?AE<aXHVWt6SR(c$?00$8F0n#Q3h+>t<pK(jO%VaKA&6SdoTFHRVj-ms|#}<$7)t@
zY<#7u&iy-~rcLPgha`Wt=ROzZZ|2T>TYRfRk#}yvO}Fp~@#!rGi_5uIBqeQISJ1Y*
zRJn6)<+o=`uKaCQGvcyVnG~(CaLz^j28r2sZMdIr{rjdNoL_vNy>`3$?(a;@j0}v6
z8{Zo=zA+F2Mvts8BjbM-4g)qI#l*;9AP*8#W|1%uYY@@Ckm)|9jPu`@>|Q;GW#8R>
z>p9{KT-Z3Y*%(<_*%=vGEDX#HOkjKi#x{+Nl9B=|ef|98;sU)yP+HSV&d&vN4UBcc
z0!6^&lbmRv2eL+<McqKvKzV`U0{J#ssMh4793-6})p|f716h!IJ{B<+5y|f9y<X9Y
z72#i&#+V9qS#mtyP-?&jlI92bgaw#O*bD^NxWM@#Ifadhk%bAEB~Wt+FikKrL>)0*
zbn_Y4yr4x4O-kiwi}WY_R9Y{hdS(@uQ^KS}drM_s`<xPeT9@r05cfOUwS@OWRc*(_
zbN7<FojNZ`+;`j@F^`R--Q%vqdgZHcU+W}1eZ8b!=H;B`Yg6KVk}SLY)(Q94I`6m>
zw`QM&!>4EbI<dl&KUSx%IF#XW@Bfx*vw40Sna!KWJ2l>dt9#ldp`7jA+<n*W-sCf`
zI_K+}aJ!{2E$OLbs=?W=|E|Hm^L}@fJ0JE){`oy{b5UI7qp<UPcDL-bh^km8=n=G=
z*R*@ey)z}VGQN5yOj+}3#b(jA2^Y>7IJaGXTEG;zrSZUu=~rI8+R(%4@ZMtbrn5@S
LuhX4VPq+dA`9+>|

literal 0
HcmV?d00001

diff --git a/xcode/keys/Apple/AppleWWDRCAG6.cer b/xcode/keys/Apple/AppleWWDRCAG6.cer
new file mode 100644
index 0000000000000000000000000000000000000000..424a70bd3b78bd3ce45167b12673d056db250ef2
GIT binary patch
literal 794
zcmXqLViq%KVw$snnTe5!Nkr-3LU*o`;>`EKZ9*rH&9}AqoO9iPi;Y98&EuRc3p2Ap
zx}mgzBpY)m3p0<9V?jYqszOkHeu;v!qk^u2yRo5~feJ{Hn@1KR>6}_rl9`s7oLG{X
zpQqqhT9T1plvz?~C~P1IQpd%^1ySdjm#k;VZNLc<WD{lz4K|Py=QT1kFg7$dGB7qb
zG>8)CH8ulsEe*gR%AnNH#lQ*T5Nn7T;rT^5Ddm|dsR}NsWvMy&1*t^}L8&=ltBVzI
zxddt{HxHA$84=DZGZ0{72Zsg|BO9xBBMXBPa}onf-VrYDd;IG{m!(!-Z@N=l8sz=a
zR!Fk*0k7c7d7R(P7hnD`nI(Utb9dXp89$un&i%h>UBCEuwt}VCHtfr{x<0X8sp7fp
z0gr!oEaYcp^_SG1D)jn)Bqi*52iw`ki3^paJQg?pGHCp6AO!TVtS}?ve-;h{HXy~s
z$Y3B35>sZ8Fc51H*}dW3!U*GzSxdTR-rKkL_4-?<RaP6gv2kd#F|x9<GcvMR8CV#Y
z!T1J@ZCV*6B?VUc`uWMl1$v2~_|!|z&joW0jCH{RMZow?PE0p8Fb7#A&thPpXP~n{
zYk@|a8dP&~Q4W$`6is?SIRjacMm`oX77=^>DawJD15VD;uzkCs=IQyR6Ov{c@PVZH
zL7rj(CPFq~0CNEYxb1s#3L6t63ll2?asp(|U@%B!GH{3!S@oo+YY{V(-5rbX4pHpu
zeseBlQ>~uwAb(`##JMk27I$d-&3i1ITN*xFCg$i*CPRkH9)F_NPJM5-(=fQ?Nx&iV
m`#SGMLj(PL3?nA&{ocH$^jO7D!QPDxpWJ7tmF-pM$p8TIXaMy9

literal 0
HcmV?d00001

diff --git a/xcode/keys/Apple/AppleWWDRCAG7.cer b/xcode/keys/Apple/AppleWWDRCAG7.cer
new file mode 100644
index 0000000000000000000000000000000000000000..df350fd3575783624fe273f20bef9ccabf5a0497
GIT binary patch
literal 1113
zcmXqLVhJ^9Vzynt%*4pVBw`{F@t^S@n|<HM`SLGq7`GgB`+w4amyJ`a&7<u*FC!x>
zD}zCjA-4f18*?ZNn=n&ou%WPlAc(^y%;i{6kdvz5nU}0*sAix7666+^g$O#Q7L{bC
zWhN(<Waj57IF^=V<QHX@R2qsIh=9~F3-dzM1?A_LC^$PB$cghB85tTHnj0CI7?>JI
z0lCI-u2GahDRwvTAiDwTN^Tw|cXLA*11GRWJk}74!t;xAQpz(^QWacM%Tjal3sQ>|
zf>Lw9?kiTn;ar0zMkVCXU}R-rZerwT0E%-lH8C<WtXX&Q^0uyx(i&6O-U|%$u{VC`
z7qfozAEryG{#sW`GI~nIQ_pKW@!*_M7-Xa)=2y`-DJ*5>-R`rGt{k^sB;;z&B$<?=
zU!QpFa-`D!)jvfRzuh)(<}Uq@8}Ar6`ET2{=~&6Cq_Ev@UCj6|K2<209Bvgm?+)Xi
ziu_D5)5Cd;hvpSsDKy(y##yzGS8Mvm4RPGkLTj~Gv)@nF{o3);NN7=LgmamVt$2gH
z=IxCu=dYf|I#=}0-P?Zr&xLEEwDp)AzrCx<+E$$KeY&Jb_f%tx$+s9(&DMoR)y)6-
zC5eT-<fZKLso~0Nv{i1U_-hosoVJ0(rbAjJ+4*|sx)}#Q>GnMiRApjjWMEv}_}-xL
zje!s_yk&(M8UM3z7_b2;CPoGWd61Ygi-dt#gNXKpO!p~eod3RL_v$$;`|j>r&k<+f
z!p5P^225q_jEpQ624)5(Funm}n?^=SNr9EVetvRsfnFjgt?4D_=YqKg#=2mEB4F}K
zPBhR1StHM)ZlG$Qyg+e*e48v(YjRNzl1`9nJ)n?*EJ!^cix`VYtdl^F^zP$9)BRlb
z3ajt55-M-jHsAwE^MicC0?Z|B1_Eqc;QWxB!p6kN!UW6`s5u0fCKwrl7ISC{r*7XW
z|ICE>?Kg??J+`ORw-&s4lVj}tZKmoJ_IZlN%voP+x%9N}bF6H-=T-mkIkz|K4)qzH
zcMtNkU2jZT*EHvd>&I99GD-%I7pW$?bpC6t3j0trsfNcTL}mNdCG*uj82t>Nn^l?P
z@Rr|%jm_!*4L-xv+-G`>H`(?dJ;l4u{R*piht115Pb5=vyQZuayu<kIX~p`rFAA>n
z#x~lyY3Zy}S$O=?gWCPFU(K?Q-do8vt6`&H+@_Se%?HEJ9LkBDx&6zAyN0(su4Og8
z+teLkD)#JoOkq;qhEIWyR^<NBI-OB`Y}pYhXHQ1El`9##+H#sZF2xjtSKazic1H5*
F1^}_yjpzUX

literal 0
HcmV?d00001

diff --git a/xcode/keys/Apple/AppleWWDRCAG8.cer b/xcode/keys/Apple/AppleWWDRCAG8.cer
new file mode 100644
index 0000000000000000000000000000000000000000..2899edb9a141633028c0d6b6b2642d23e3fb3a29
GIT binary patch
literal 1113
zcmXqLVhJ^9Vzynt%*4pVBoeZfdwnHuZ+*}D44*LlfJ`o_UGWCIY@Awc9&O)w85vnw
z84QvPxeYkkm_u3EgqcEv4TTK^K^!h&F2{m`oKywRyktE?H3JopAh)nAM9?|4s3bEj
zGdZy&Ge1wkv9u&3zbLb$(ooDm1f-5xm=~fhC_leM!P(J3PMp`s*uc!lz{uFx+|V=%
z$Tc-EG%_&&gD8Vi>~7#eb_3Lv+&oO~7KSbcPGF08tRWVK=NILqlxL=-D!8PUrRL-p
zq!uXzrRIR$SFC`;xdu&)O30zX$jZRn#K_M86z5`UVq|2v;2>~?<7bd!vcFBn_bYRn
zn0lHs_H6I1?|AOytMguI>7mYhdwH(=CI;wQJ~1d>dg*G$EaOk_Z)&a8lV{%bW9dgH
z?r=S~V;3SW7sP+xWd1%&-fn-V<)O9zzOw#~m}YpQUFWLuuF?%UUso^K^+|!p=e0_5
z=1V1q4}B5Q_fo1mr2~an9*A#>JbVA+^K<KUj9z3OyueW>yU4xxqPO+movnA=muoat
zYI<}sX*@dkMn^un?az&Erwb1hGkX7F6%@>2WHyQV)_5pRzD9)ao_)6BY5%X+6Q8v(
zPulZbRde3iXr6<&A0M&0Sr)!V-$F$4#P*GgLjB|Y`XnP)-uhc~YXgfSD-$y#1LNYx
z_Xdq`41|E;Ei25(_@9NtfDK47F)|p)gT$0sBn-qFM6@qtx=$(N{P!ihSI=SDcX!`<
zjyMAsHV$nzU@Bv0WMr{0Ff%ZL@eLT;G%`v`3as??^OK7U^b$d7O)oh=7tA#<)&&a`
z0h3R1qJbXB8hI9V162d%1&Ryg+hn0ylZ$eYbb?gt0fh`?LF)Nf#8^bO?%mUHgy*rv
zk}uoWDsO)8a&Bi-s{tQKnjhp77GN%6GZ0|o0_TV16gDPC7A9bpK+Pe*G{MN=v-x$E
z<rJ@}X}`n_U-5SJ$2wUYV?X=iq|%x{98Pudlj9AwRwx}Tlhl5<uIT07u=AcOlQ_Pg
zl`K8{Q%aqe?~Z1#{kGdn{e6m#BuwlStW%lltdx+x=l=iIPi@4+=QfG>&HYmPFJR|d
z)=fJqzfHX+@bp{om-EWc%K6{y@Xq}4XdaW{&Aywb_9e%~KU|P`?%>%x&&3sq>n&}v
zytzzNQ?43pwOM^vu+g&c#eu^S4T1tvf|m~MiTu!Y)3o@&v)m^qYm-FmnwVA!WSUnd
z=6`UTVrTkw^_t`hH{v40GcWG&&WpVgFFdEfPgU@aijJJvylGJ^Z(ZM6y-SbnKiszA
JtB-t!005Iwl`sGR

literal 0
HcmV?d00001