Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cdc40774c4 | |||
| 5847294a80 | |||
| 343481d053 | |||
| 13a3dc4890 | |||
| 526dedd653 | |||
| 9b3ac8c31c | |||
| cd2ba37db6 | |||
| 7be2ef27b9 | |||
| b7e4931e64 | |||
| a3bfd42759 | |||
| 1587db4edf | |||
| a516f0570d | |||
| 7cbdc3cdb7 | |||
| 7f27ee1b4e | |||
| 4f9c73e90f | |||
| e3359320fc | |||
| 9073a51787 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,6 +32,9 @@ playground.xcworkspace
|
||||
|
||||
.build/
|
||||
|
||||
# Generated by xcodegen in CI — do not commit
|
||||
*.xcodeproj/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
|
||||
@@ -12,7 +12,7 @@ final class AppEnvironment: ObservableObject {
|
||||
let apiClient: SilverAPIClient
|
||||
let mdmService: MDMEnrollmentService
|
||||
|
||||
private var serverUrl: String {
|
||||
var serverUrl: String {
|
||||
UserDefaults.standard.string(forKey: "silverapple.serverUrl") ?? ""
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ final class PassportAuthService: NSObject, ObservableObject, ASWebAuthentication
|
||||
|
||||
let authUrl = buildAuthURL(challenge: challenge)
|
||||
|
||||
let callbackUrl = try await withCheckedThrowingContinuation { continuation in
|
||||
let callbackUrl: URL = try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<URL, any Error>) in
|
||||
let session = ASWebAuthenticationSession(url: authUrl, callbackURLScheme: "silverapple") { url, error in
|
||||
if let error { continuation.resume(throwing: error); return }
|
||||
guard let url else { continuation.resume(throwing: AuthError.noCallback); return }
|
||||
|
||||
16
SilverApple/Hardening/Views/HardeningListView.swift
Normal file
16
SilverApple/Hardening/Views/HardeningListView.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
import SwiftUI
|
||||
|
||||
struct HardeningListView: View {
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
Section {
|
||||
Label("Privacy hardening checks coming soon.", systemImage: "lock.shield")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.subheadline)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Hardening")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ struct MDMEnrollmentView: View {
|
||||
VStack(spacing: 32) {
|
||||
Image(systemName: "iphone.badge.play")
|
||||
.font(.system(size: 56))
|
||||
.foregroundStyle(.accentColor)
|
||||
.foregroundStyle(Color.accentColor)
|
||||
|
||||
VStack(spacing: 12) {
|
||||
Text("Device Management")
|
||||
|
||||
29
SilverApple/Settings/Views/ServerConfigView.swift
Normal file
29
SilverApple/Settings/Views/ServerConfigView.swift
Normal file
@@ -0,0 +1,29 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ServerConfigView: View {
|
||||
@EnvironmentObject var env: AppEnvironment
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
Section("Server") {
|
||||
HStack {
|
||||
Text("URL")
|
||||
Spacer()
|
||||
Text(env.serverUrl.isEmpty ? "Not configured" : env.serverUrl)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Button("Sign Out", role: .destructive) {
|
||||
env.authService.signOut()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Settings")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,23 @@
|
||||
"name": "SilverApple",
|
||||
"bundleIdentifier": "uk.silverlabs.silverapple",
|
||||
"developerName": "SilverLABS",
|
||||
"downloadURL": "",
|
||||
"downloadURL": "https://git.silverlabs.uk/SilverLABS/SilverApple/releases/download/v0.1.1/SilverApple.ipa",
|
||||
"subtitle": "Privacy companion for iOS",
|
||||
"localizedDescription": "SilverApple integrates your device with the SilverLABS ecosystem — MDM enrollment, privacy hardening checks, and Passport authentication.",
|
||||
"iconURL": "https://git.silverlabs.uk/SilverLABS/SilverApple/raw/branch/main/SilverApple/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png",
|
||||
"tintColor": "00BBFF",
|
||||
"category": "utilities",
|
||||
"versions": []
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.1.1",
|
||||
"buildVersion": "0.1.1",
|
||||
"date": "2026-04-06T21:22:41Z",
|
||||
"localizedDescription": "See release notes.",
|
||||
"downloadURL": "https://git.silverlabs.uk/SilverLABS/SilverApple/releases/download/v0.1.1/SilverApple.ipa",
|
||||
"sha256": "fa2004dee56567a11b134461bc3736417a2f84f015bf2944e6872fda020e0399",
|
||||
"size": 91467
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"news": []
|
||||
|
||||
107
codemagic.yaml
107
codemagic.yaml
@@ -13,39 +13,85 @@ workflows:
|
||||
|
||||
environment:
|
||||
xcode: latest
|
||||
groups:
|
||||
- SLABS
|
||||
- APPLE_SIGNING
|
||||
vars:
|
||||
BUNDLE_ID: uk.silverlabs.silverapple
|
||||
GITEA_REPO: SilverLABS/SilverApple
|
||||
GITEA_API: https://git.silverlabs.uk/api/v1
|
||||
# GITEA_TOKEN — set this in Codemagic App Settings → Environment variables (mark as secret)
|
||||
|
||||
scripts:
|
||||
- name: Build archive (unsigned)
|
||||
- name: Generate Xcode project
|
||||
script: |
|
||||
brew install xcodegen
|
||||
xcodegen generate --spec project.yml
|
||||
|
||||
- name: Initialize keychain
|
||||
script: keychain initialize
|
||||
|
||||
- name: Install signing certificate
|
||||
script: |
|
||||
echo $CM_CERTIFICATE | base64 --decode > /tmp/cert.p12
|
||||
keychain add-certificates \
|
||||
--certificate /tmp/cert.p12 \
|
||||
--certificate-password $CM_CERTIFICATE_PASSWORD
|
||||
|
||||
- name: Install provisioning profile
|
||||
script: |
|
||||
echo $CM_PROVISIONING_PROFILE | base64 --decode > /tmp/profile.mobileprovision
|
||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||
cp /tmp/profile.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/
|
||||
|
||||
- name: Configure Xcode signing
|
||||
script: xcode-project use-profiles
|
||||
|
||||
- name: Build (signed)
|
||||
script: |
|
||||
xcodebuild archive \
|
||||
-project SilverApple.xcodeproj \
|
||||
-scheme SilverApple \
|
||||
-destination "generic/platform=iOS" \
|
||||
-configuration Release \
|
||||
-archivePath "$CM_BUILD_DIR/SilverApple.xcarchive" \
|
||||
CODE_SIGNING_ALLOWED=NO \
|
||||
CODE_SIGNING_REQUIRED=NO \
|
||||
CODE_SIGN_IDENTITY="" \
|
||||
PROVISIONING_PROFILE=""
|
||||
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
|
||||
CODE_SIGN_STYLE=Manual
|
||||
|
||||
- name: Package IPA
|
||||
- name: Export signed IPA
|
||||
script: |
|
||||
cd "$CM_BUILD_DIR"
|
||||
mkdir -p Payload
|
||||
cp -r SilverApple.xcarchive/Products/Applications/SilverApple.app Payload/
|
||||
zip -r SilverApple.ipa Payload/
|
||||
rm -rf Payload
|
||||
echo "IPA size: $(du -sh SilverApple.ipa | cut -f1)"
|
||||
cat > /tmp/ExportOptions.plist << 'EOF'
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>method</key>
|
||||
<string>ad-hoc</string>
|
||||
<key>signingStyle</key>
|
||||
<string>manual</string>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
xcodebuild -exportArchive \
|
||||
-archivePath "$CM_BUILD_DIR/SilverApple.xcarchive" \
|
||||
-exportPath "$CM_BUILD_DIR/export" \
|
||||
-exportOptionsPlist /tmp/ExportOptions.plist
|
||||
cp "$CM_BUILD_DIR/export/SilverApple.ipa" "$CM_BUILD_DIR/SilverApple.ipa"
|
||||
|
||||
- name: Publish to Gitea
|
||||
script: |
|
||||
set -e
|
||||
TAG="$CM_TAG"
|
||||
set -exo pipefail
|
||||
[ -n "$GITEA_TOKEN" ] || { echo "ERROR: GITEA_TOKEN is not set in Codemagic env vars"; exit 1; }
|
||||
echo "TAG=$CM_TAG BUILD_DIR=$CM_BUILD_DIR"
|
||||
echo "GITEA_API=$GITEA_API TOKEN_SET=yes"
|
||||
|
||||
TAG="${CM_TAG:-$(git tag --points-at HEAD | head -1)}"
|
||||
[ -n "$TAG" ] || { echo "ERROR: could not determine tag"; exit 1; }
|
||||
VERSION="${TAG#v}"
|
||||
IPA="$CM_BUILD_DIR/SilverApple.ipa"
|
||||
|
||||
# Verify IPA exists
|
||||
ls -lh "$IPA"
|
||||
|
||||
SHA256=$(shasum -a 256 "$IPA" | awk '{print $1}')
|
||||
SIZE=$(wc -c < "$IPA" | tr -d ' ')
|
||||
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
@@ -64,27 +110,36 @@ workflows:
|
||||
altstore-source.json > altstore-source.tmp.json
|
||||
mv altstore-source.tmp.json altstore-source.json
|
||||
|
||||
# Commit and push updated source
|
||||
git remote set-url origin "https://sysadmin:$GITEA_TOKEN@git.silverlabs.uk/$GITEA_REPO.git"
|
||||
git config user.name "Codemagic"
|
||||
git config user.email "ci@silverlabs.uk"
|
||||
git add altstore-source.json
|
||||
git commit -m "chore(altstore): update source for $TAG" || echo "No changes"
|
||||
git push origin HEAD:main
|
||||
# Get current file SHA from Gitea API
|
||||
FILE_SHA=$(curl -s \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_API/repos/$GITEA_REPO/contents/altstore-source.json" \
|
||||
| jq -r '.sha')
|
||||
echo "FILE_SHA=$FILE_SHA"
|
||||
|
||||
# Update altstore-source.json via Gitea contents API
|
||||
CONTENT=$(base64 -i altstore-source.json | tr -d '\n')
|
||||
curl -s -X PUT "$GITEA_API/repos/$GITEA_REPO/contents/altstore-source.json" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"message\":\"chore(altstore): update source for $TAG\",\"content\":\"$CONTENT\",\"sha\":\"$FILE_SHA\",\"branch\":\"main\"}" \
|
||||
| jq -r '.commit.sha // "FAILED"'
|
||||
|
||||
# Create Gitea release
|
||||
RELEASE_ID=$(curl -sf -X POST "$GITEA_API/repos/$GITEA_REPO/releases" \
|
||||
RELEASE_ID=$(curl -s -X POST "$GITEA_API/repos/$GITEA_REPO/releases" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"$TAG\",\"name\":\"SilverApple $TAG\",\"body\":\"AltStore / SideStore release.\",\"draft\":false,\"prerelease\":false}" \
|
||||
| jq -r '.id')
|
||||
echo "RELEASE_ID=$RELEASE_ID"
|
||||
|
||||
# Upload IPA
|
||||
curl -sf -X POST "$GITEA_API/repos/$GITEA_REPO/releases/$RELEASE_ID/assets" \
|
||||
curl -s -X POST "$GITEA_API/repos/$GITEA_REPO/releases/$RELEASE_ID/assets" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-F "attachment=@$IPA;type=application/octet-stream"
|
||||
-F "attachment=@$IPA;type=application/octet-stream" \
|
||||
| jq -r '.name // "UPLOAD_FAILED"'
|
||||
|
||||
echo "Published release $TAG → $DOWNLOAD_URL"
|
||||
echo "Done: $TAG → $DOWNLOAD_URL"
|
||||
|
||||
artifacts:
|
||||
- $CM_BUILD_DIR/SilverApple.ipa
|
||||
|
||||
43
project.yml
Normal file
43
project.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
name: SilverApple
|
||||
options:
|
||||
bundleIdPrefix: uk.silverlabs
|
||||
deploymentTarget:
|
||||
iOS: "16.0"
|
||||
xcodeVersion: "15"
|
||||
generateEmptyDirectories: true
|
||||
|
||||
targets:
|
||||
SilverApple:
|
||||
type: application
|
||||
platform: iOS
|
||||
deploymentTarget: "16.0"
|
||||
sources:
|
||||
- path: SilverApple
|
||||
excludes:
|
||||
- Info.plist
|
||||
- SilverApple.entitlements
|
||||
resources:
|
||||
- SilverApple/Assets.xcassets
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: uk.silverlabs.silverapple
|
||||
INFOPLIST_FILE: SilverApple/Info.plist
|
||||
CODE_SIGN_ENTITLEMENTS: SilverApple/SilverApple.entitlements
|
||||
SWIFT_VERSION: "5.9"
|
||||
TARGETED_DEVICE_FAMILY: "1,2"
|
||||
OTHER_LDFLAGS:
|
||||
- "-framework AuthenticationServices"
|
||||
- "-framework SafariServices"
|
||||
- "-framework Security"
|
||||
|
||||
SilverAppleTests:
|
||||
type: bundle.unit-test
|
||||
platform: iOS
|
||||
deploymentTarget: "16.0"
|
||||
sources:
|
||||
- path: SilverAppleTests
|
||||
dependencies:
|
||||
- target: SilverApple
|
||||
settings:
|
||||
base:
|
||||
SWIFT_VERSION: "5.9"
|
||||
8
servers.json
Normal file
8
servers.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"name": "SilverLABS Anisette",
|
||||
"address": "https://anisette.silverlabs.uk"
|
||||
}
|
||||
]
|
||||
}
|
||||
17
xtool.yml
17
xtool.yml
@@ -1,13 +1,8 @@
|
||||
# xTool configuration — https://xtool.sh
|
||||
# Run `xtool configure` once to set up your Apple ID credentials and Darwin SDK.
|
||||
# Then: `xtool run` to build and install directly to a connected device.
|
||||
# Run `xtool setup` once to configure your Apple ID credentials and extract the Darwin SDK.
|
||||
# Then: `xtool dev` to build and deploy directly to a connected USB device.
|
||||
|
||||
targets:
|
||||
SilverApple:
|
||||
bundleIdentifier: uk.silverlabs.silverapple
|
||||
# Fill in your Apple Developer Team ID (10-char string from developer.apple.com)
|
||||
teamID: ""
|
||||
infoPlist: SilverApple/Info.plist
|
||||
entitlements: SilverApple/SilverApple.entitlements
|
||||
deploymentTarget: "16.0"
|
||||
deviceFamily: [iphone]
|
||||
version: 1
|
||||
bundleID: uk.silverlabs.silverapple
|
||||
infoPath: SilverApple/Info.plist
|
||||
entitlementsPath: SilverApple/SilverApple.entitlements
|
||||
|
||||
Reference in New Issue
Block a user