Prepare Apple App Store distribution (#59)
69
apple/AppStore/DISTRIBUTION.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Apple App Store distribution
|
||||
|
||||
Use `distribution/` only as ignored local staging. Never store Apple credentials,
|
||||
signing material, review credentials, GPG material, application tokens, or
|
||||
private diagnostics in the repository or release logs.
|
||||
|
||||
## Release identity
|
||||
|
||||
- iPhone application: `de.rfc1437.ironstorage`
|
||||
- AutoFill extension: `de.rfc1437.ironstorage.autofill`
|
||||
- Apple Watch companion: `de.rfc1437.ironstorage.watch`
|
||||
- Apple Developer team: `MU22FMRGK8`
|
||||
|
||||
The submitted archive must embed the Watch application beneath the iPhone
|
||||
application. An iPhone-only archive is not a releasable IronStorage build.
|
||||
|
||||
## Prepare and submit
|
||||
|
||||
1. Generate the project and release attribution, then run the release verifier:
|
||||
|
||||
```sh
|
||||
cargo metadata --format-version 1 --filter-platform aarch64-apple-ios \
|
||||
> /private/tmp/ironstorage-ios-metadata.json
|
||||
cargo run -p ironstorage-apple-release -- licenses \
|
||||
/private/tmp/ironstorage-ios-metadata.json \
|
||||
apple/Resources/App/ThirdPartyLicenses.txt
|
||||
cargo run -p ironstorage-apple-release -- verify .
|
||||
```
|
||||
|
||||
2. Run the repository gates and build both simulator applications. Validate the
|
||||
local-first flow with synthetic data: generate or import a GPG key, create
|
||||
folders and encrypted entries, read TOTP codes, select Watch entries, and
|
||||
verify the Watch list and selected-code progress display.
|
||||
3. Create the production archive with normal App Store distribution signing:
|
||||
|
||||
```sh
|
||||
cd apple
|
||||
xcodegen generate
|
||||
xcodebuild -project IronStorage.xcodeproj -scheme IronStorage \
|
||||
-configuration Release -destination 'generic/platform=iOS' \
|
||||
-archivePath /private/tmp/IronStorage.xcarchive archive
|
||||
```
|
||||
|
||||
4. Inspect the archive before upload. The iPhone, AutoFill, and Watch bundle
|
||||
identifiers and versions must match the metadata; the Watch app must be
|
||||
embedded; privacy manifests and license resources must be present; the
|
||||
archive must use distribution signing and must not contain `get-task-allow`,
|
||||
simulator artifacts, synthetic demo data, private endpoints, or secrets.
|
||||
5. Export and upload with the checked-in App Store Connect export options:
|
||||
|
||||
```sh
|
||||
xcodebuild -exportArchive \
|
||||
-archivePath /private/tmp/IronStorage.xcarchive \
|
||||
-exportPath /private/tmp/IronStorage-AppStore \
|
||||
-exportOptionsPlist AppStore/ExportOptions.plist
|
||||
```
|
||||
|
||||
6. In App Store Connect, complete the listing from `metadata.toml`, upload the
|
||||
reviewed screenshots, answer privacy and encryption questions, provide
|
||||
local-first review instructions, select the processed build, and submit it
|
||||
for review. Do not provide a production password store or real credentials.
|
||||
7. After approval, install the public release from the App Store on the paired
|
||||
iPhone and Apple Watch. Verify local onboarding, key overwrite confirmation,
|
||||
local Git history, folders, encrypted entries, Face ID, TOTP, optional HTTPS
|
||||
pull and push, Watch snapshot delivery, the Watch entry-only list, and the
|
||||
larger selected code with its validity progress indicator.
|
||||
8. Verify an App Store update in place. Verify the documented uninstall and
|
||||
reinstall Keychain lifecycle only with disposable test data; never erase the
|
||||
paired physical device or its unrelated IronStorage data.
|
||||
20
apple/AppStore/ExportOptions.plist
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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>destination</key>
|
||||
<string>upload</string>
|
||||
<key>manageAppVersionAndBuildNumber</key>
|
||||
<false/>
|
||||
<key>method</key>
|
||||
<string>app-store-connect</string>
|
||||
<key>signingStyle</key>
|
||||
<string>automatic</string>
|
||||
<key>stripSwiftSymbols</key>
|
||||
<true/>
|
||||
<key>teamID</key>
|
||||
<string>MU22FMRGK8</string>
|
||||
<key>uploadSymbols</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
52
apple/AppStore/apps-index.html
Normal file
@@ -0,0 +1,52 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>rfc1437 Apps</title>
|
||||
<link rel="stylesheet" href="/assets/pico.pumpkin.min.css">
|
||||
<link rel="stylesheet" href="/assets/bds.css">
|
||||
<style>.app-header{display:flex;align-items:center;gap:1rem}.app-header img{width:5rem;height:5rem;border-radius:1.1rem}.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));gap:1rem}figure{margin:0}figure img{display:block;width:100%;height:auto;border-radius:1.5rem}figcaption{margin-top:.5rem;color:var(--pico-muted-color)}</style>
|
||||
</head>
|
||||
<body><main>
|
||||
<header><h1 class="archive-heading">rfc1437 Apps</h1><p>Small, focused apps published by <a href="https://rfc1437.de/">rfc1437</a>.</p></header>
|
||||
<nav class="blog-menu" aria-label="Site navigation"><ul class="blog-menu-list"><li class="blog-menu-item"><a class="blog-menu-link" href="https://rfc1437.de/">Home</a></li><li class="blog-menu-item"><span class="blog-menu-link" aria-current="page">Apps</span></li></ul></nav>
|
||||
<article class="post">
|
||||
<h2>Install</h2>
|
||||
<p>Gotcha is available through the rfc1437 AltStore PAL source at <code>https://rfc1437.de/apps/source.json</code>.</p>
|
||||
<p>IronStorage is being prepared for the Apple App Store so its iPhone app and Apple Watch companion install together through the supported App Store path.</p>
|
||||
</article>
|
||||
<section><h2>Apps</h2>
|
||||
<article class="post">
|
||||
<header class="app-header"><img src="gotcha/icon.png" alt="Gotcha app icon"><div><h3>Gotcha</h3><p>Native Gitea and Forgejo on iPhone.</p></div></header>
|
||||
<p>Follow repositories, issues, pull requests, commits, diffs, and milestones on servers you control.</p>
|
||||
<nav><a href="gotcha/privacy/">Privacy</a> · <a href="https://git.rfc1437.de/hugo/Gotcha">Source</a> · <a href="https://git.rfc1437.de/hugo/Gotcha/issues">Support</a></nav>
|
||||
<div class="gallery">
|
||||
<figure><img src="gotcha/screenshots/01-home-activity.png" alt="Gotcha activity"><figcaption>Activity</figcaption></figure>
|
||||
<figure><img src="gotcha/screenshots/02-issues.png" alt="Gotcha issues"><figcaption>Issues</figcaption></figure>
|
||||
<figure><img src="gotcha/screenshots/03-commit-history.png" alt="Gotcha commits"><figcaption>Commits</figcaption></figure>
|
||||
<figure><img src="gotcha/screenshots/04-diff.png" alt="Gotcha diff"><figcaption>Diffs</figcaption></figure>
|
||||
<figure><img src="gotcha/screenshots/05-pull-request.png" alt="Gotcha pull request"><figcaption>Pull requests</figcaption></figure>
|
||||
<figure><img src="gotcha/screenshots/06-milestones.png" alt="Gotcha milestones"><figcaption>Milestones</figcaption></figure>
|
||||
</div>
|
||||
</article>
|
||||
<article class="post">
|
||||
<header class="app-header"><img src="ironstorage/icon.png" alt="IronStorage app icon"><div><h3>IronStorage</h3><p>Native pass and pass-otp on iPhone and Apple Watch.</p></div></header>
|
||||
<p>Generate or import a protected GPG key, keep local Git history, create encrypted entries and TOTP codes, and add optional HTTPS synchronization later.</p>
|
||||
<p><strong>Apple App Store release in preparation.</strong></p>
|
||||
<nav><a href="ironstorage/privacy/">Privacy</a> · <a href="https://git.rfc1437.de/hugo/IronStorage">Source</a> · <a href="https://git.rfc1437.de/hugo/IronStorage/issues">Support</a></nav>
|
||||
<div class="gallery">
|
||||
<figure><img src="ironstorage/screenshots/01-home.png" alt="IronStorage local Git home"><figcaption>Local Git status</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/02-passwords.png" alt="IronStorage password folders"><figcaption>Passwords and folders</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/03-totp.png" alt="IronStorage TOTP list"><figcaption>TOTP and Watch selection</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/04-totp-detail.png" alt="IronStorage TOTP detail"><figcaption>Live TOTP detail</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/05-preferences.png" alt="IronStorage preferences"><figcaption>Local-first preferences</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/06-search.png" alt="IronStorage search"><figcaption>Password search</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/watch-01-list.png" alt="IronStorage Watch entry list"><figcaption>Watch entry list</figcaption></figure>
|
||||
<figure><img src="ironstorage/screenshots/watch-02-detail.png" alt="IronStorage Watch code detail"><figcaption>Watch code and progress</figcaption></figure>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
<footer><small>Both apps are free and open-source software. Each listing identifies its supported distribution channel.</small></footer>
|
||||
</main></body></html>
|
||||
26
apple/AppStore/index.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>IronStorage</title>
|
||||
<style>body{font:17px system-ui;line-height:1.55;max-width:64rem;margin:3rem auto;padding:0 1rem;color:#1d1d1f}header{display:flex;align-items:center;gap:1rem}header img{width:6rem;border-radius:1.3rem}.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));gap:1rem}.gallery img{width:100%;border-radius:1.5rem}nav{margin:1.5rem 0}</style>
|
||||
<header><img src="icon.png" alt="IronStorage app icon"><div><h1>IronStorage</h1><p>Native pass and pass-otp for iPhone and Apple Watch.</p></div></header>
|
||||
<p>Start locally with a protected GPG key and versioned password store. Create folders and encrypted entries on your iPhone, generate TOTP codes, and optionally connect an HTTPS Git remote later.</p>
|
||||
<p>The Apple Watch companion receives only the TOTP entries you explicitly share.</p>
|
||||
<p><strong>Apple App Store release in preparation.</strong></p>
|
||||
<nav><a href="privacy/">Privacy</a> · <a href="https://git.rfc1437.de/hugo/IronStorage">Source code</a> · <a href="https://git.rfc1437.de/hugo/IronStorage/issues">Support</a></nav>
|
||||
<div class="gallery">
|
||||
<img src="screenshots/01-home.png" alt="Local Git status">
|
||||
<img src="screenshots/02-passwords.png" alt="Password entries and folders">
|
||||
<img src="screenshots/03-totp.png" alt="TOTP entries selected for Apple Watch">
|
||||
<img src="screenshots/04-totp-detail.png" alt="Live TOTP detail">
|
||||
<img src="screenshots/05-preferences.png" alt="Local-first preferences">
|
||||
<img src="screenshots/06-search.png" alt="Password search">
|
||||
</div>
|
||||
<h2>Apple Watch</h2>
|
||||
<div class="gallery">
|
||||
<img src="screenshots/watch-01-list.png" alt="Apple Watch TOTP entry list">
|
||||
<img src="screenshots/watch-02-detail.png" alt="Apple Watch selected code and progress bar">
|
||||
</div>
|
||||
</html>
|
||||
74
apple/AppStore/metadata.toml
Normal file
@@ -0,0 +1,74 @@
|
||||
[app]
|
||||
name = "IronStorage"
|
||||
bundle_identifier = "de.rfc1437.ironstorage"
|
||||
developer_name = "rfc1437"
|
||||
subtitle = "Native pass on iPhone"
|
||||
description = "IronStorage is a native iPhone and Apple Watch client for pass and pass-otp password stores. Start entirely on-device with a protected GPG key and local Git history, then add optional HTTPS Git synchronization whenever you want it."
|
||||
keywords = "password,gpg,pass,totp,git,security,watch"
|
||||
icon_file = "apple/Assets.xcassets/AppIcon.appiconset/AppIcon.png"
|
||||
category = "utilities"
|
||||
privacy_url = "https://rfc1437.de/apps/ironstorage/privacy/"
|
||||
support_url = "https://git.rfc1437.de/hugo/IronStorage/issues"
|
||||
marketing_url = "https://rfc1437.de/apps/ironstorage/"
|
||||
age_rating = "4+"
|
||||
|
||||
[release]
|
||||
version = "0.1.0"
|
||||
build = "1"
|
||||
minimum_ios = "17.0"
|
||||
notes = "Initial iPhone and Apple Watch release with local GPG key generation, pass-compatible local Git history, optional HTTPS synchronization, password folders, and explicitly shared TOTP codes on Apple Watch."
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/home.png"
|
||||
caption = "Local Git history works before a sync remote is configured"
|
||||
width = 1206
|
||||
height = 2622
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/passwords.png"
|
||||
caption = "Password entries and folders stay organized on device"
|
||||
width = 1206
|
||||
height = 2622
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/totp.png"
|
||||
caption = "TOTP entries are shared with Apple Watch only when selected"
|
||||
width = 1206
|
||||
height = 2622
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/totp-detail.png"
|
||||
caption = "Live TOTP codes include an exact validity indicator"
|
||||
width = 1206
|
||||
height = 2622
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/preferences.png"
|
||||
caption = "Generate or import a GPG key and add optional HTTPS sync later"
|
||||
width = 1206
|
||||
height = 2622
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/search.png"
|
||||
caption = "Search encrypted password entries by name or folder"
|
||||
width = 1206
|
||||
height = 2622
|
||||
|
||||
[[watch_screenshots]]
|
||||
file = "apple/AppStore/screenshots/watch-list.png"
|
||||
caption = "The Watch list shows only explicitly shared TOTP entries"
|
||||
width = 416
|
||||
height = 496
|
||||
|
||||
[[watch_screenshots]]
|
||||
file = "apple/AppStore/screenshots/watch-detail.png"
|
||||
caption = "The selected Watch code is large with a validity progress bar"
|
||||
width = 416
|
||||
height = 496
|
||||
|
||||
[content]
|
||||
advertising = false
|
||||
account_creation = false
|
||||
digital_purchases = false
|
||||
tracking = false
|
||||
user_generated_content = false
|
||||
18
apple/AppStore/privacy/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>IronStorage Privacy</title>
|
||||
<style>body{font:17px system-ui;line-height:1.55;max-width:44rem;margin:3rem auto;padding:0 1rem;color:#1d1d1f}h1,h2{line-height:1.2}</style>
|
||||
<h1>IronStorage Privacy</h1>
|
||||
<p>Last updated: 16 August 2026</p>
|
||||
<p>IronStorage does not collect analytics, advertising identifiers, diagnostics, or personal data for the developer, and it does not track you.</p>
|
||||
<h2>Data on your device</h2>
|
||||
<p>Your local Git repository and encrypted password entries remain on your device. Application tokens, imported or generated private-key material, and protected unlock data use Apple Keychain storage. Camera frames used to scan a key-transfer QR code are processed on the device and are not retained by IronStorage.</p>
|
||||
<h2>Network access</h2>
|
||||
<p>IronStorage works without a network service. If you later configure an HTTPS Git server, it connects only to that server using the credentials you provide to pull and push your password store. The developer does not operate an IronStorage service and does not receive this traffic.</p>
|
||||
<h2>Deletion</h2>
|
||||
<p>Remove configured credentials and key material in IronStorage before uninstalling when you want them deleted immediately. Keychain items otherwise follow Apple’s secure-storage lifecycle and may survive an app reinstall.</p>
|
||||
<h2>Support</h2>
|
||||
<p>Questions and issues can be filed at <a href="https://git.rfc1437.de/hugo/IronStorage/issues">the IronStorage issue tracker</a>.</p>
|
||||
</html>
|
||||
BIN
apple/AppStore/screenshots/home.png
Normal file
|
After Width: | Height: | Size: 235 KiB |
BIN
apple/AppStore/screenshots/passwords.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
apple/AppStore/screenshots/preferences.png
Normal file
|
After Width: | Height: | Size: 364 KiB |
BIN
apple/AppStore/screenshots/search.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
apple/AppStore/screenshots/totp-detail.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
apple/AppStore/screenshots/totp.png
Normal file
|
After Width: | Height: | Size: 221 KiB |
BIN
apple/AppStore/screenshots/watch-detail.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
apple/AppStore/screenshots/watch-list.png
Normal file
|
After Width: | Height: | Size: 45 KiB |