new app store assets ready for relese

This commit is contained in:
Mark Gregory
2026-11-04 16:09:22 +00:00
parent 1a50eb762d
commit c217b0dfc8
36 changed files with 372 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
# Tarnax App Store release pack
Prepared for version 1.0, build 8. Support: mark.gregory@abbeysoftware.com.
Open `index.html` to browse the assets. This folder is a local preparation pack; nothing has been uploaded or published.
## Upload assets
- `screenshots/upload/iphone-6.9`: six finished portrait PNGs, 1320 × 2868.
- `screenshots/upload/ipad-13`: six finished portrait PNGs, 2064 × 2752.
- `screenshots/raw`: untouched underlying app captures with fictitious lawful sample data.
- `icons/Tarnax-AppStore-1024.png`: opaque master icon. Smaller icons support website/press use; Xcode's existing asset catalog supplies the app icon.
- `previews`: optional 24-second silent H.264 app previews and posters, iPhone 886 × 1920 and iPad 1200 × 1600. These present six static views from actual simulator footage; they do not demonstrate live gestures or a real server session. Preview them before choosing whether to upload.
- `metadata/en-GB` and `en-US`: app name, subtitle, description, promotional text, keywords and first-release notes.
- `marketing`: social artwork, press header, brand guide and contact sheets. These are not App Store screenshot uploads.
## Privacy, support and review
`website/` is a complete static support/marketing/privacy website. Publish only this directory on your chosen host. No hosting address has been invented. Add the resulting support and privacy URLs to `release-config.json` and App Store Connect.
`legal/` includes privacy policy, usage information and the privacy manifest also bundled in the app. `review/` contains reviewer instructions, the dedicated review-server checklist, proposed privacy-label assessment, age-rating worksheet and release checklist. Complete and confirm the assessments against your actual operating practices.
Supply an externally reachable, dedicated qBittorrent review server with disposable lawful content and credentials directly in App Store Connect. The screenshot fixture is isolated in Scratch, is not compiled into the production archive and does not replace reviewer access. Do not put passwords into this folder.
Outstanding owner decisions are recorded as nulls in `release-config.json`: website URLs, price, territories and reviewer contact phone. Naming rights, agreements, content rights, privacy and age-rating answers also require your confirmation. Earlier name searches do not establish trademark clearance.
## Build and reproduce
Run `scripts/test.sh --contracts-only` from the project. All 83 checks passed during preparation, and the Release archive built successfully. `appstore/tools/archive.sh` creates an App Store archive and attempts a local IPA export using existing signing assets. The optional `--allow-provisioning-updates` flag requires permission to update your developer account. A direct-install IPA is not an App Store upload binary.
Capture and rendering scripts in `tools/` use temporary files beneath `~/Developer/Scratch/Tarnax`. `capture.sh` builds an isolated fixture copy, `render_assets.py` uses Pillow, `make_previews.py` needs ffmpeg, and `build_website.py` regenerates the website. Run `validate.py` with a Python environment containing Pillow; add `--submission-ready` to require owner setup as well. `validation-report.json` records the latest result and `SHA256SUMS` records asset hashes.
Build archives under `build/` are private local release materials; do not publish them with the website. See `SOURCES.md` for Apple's requirements and `review/release-checklist.md` for final submission steps. No App Store acceptance or legal clearance is implied by local validation.
+86
View File
@@ -0,0 +1,86 @@
814301cd2ff741349e261e624d67809174caa6a08b2d94df3087f368f2f97e03 README.md
0d1add7f9c86aaf802a9dd94b656c7b7bc5a5f28bc1f30e216ab41f82bfd4461 SOURCES.md
c0e22e36f2c5f92802c6797c069cc58af6f68664e31a5d50bb774e33283dec75 asset-manifest.json
18605382e1371769278f7d9cc30952886e87ce9c2192078480d8f449d68fffad icons/Tarnax-128.png
8eccf035da8692920262e9f917b6f2971f9a9386a0125d773fb778a53367e0ed icons/Tarnax-180.png
2aefc2583182234d263fb6bea8662a4bde0bd17030811cd50243d99bd544f402 icons/Tarnax-256.png
283777a7ae895a7e6f0dc0b76c17597eec98d522ed8564eac48bc88aa466d1e3 icons/Tarnax-32.png
adc9b33c96681be7a55ad93da090f07406653df48e1c1657f651c1fbaddf8329 icons/Tarnax-512.png
2383de3a526e25413c992a6185230b71aa8c52bb23a33f369eb38bf173ee6bd5 icons/Tarnax-64.png
0dd661c392e1704bdbf1b34db1a32ec5c1f063d5f8565f84d0df69b8383e0e19 icons/Tarnax-AppStore-1024.png
362a665353a95c17045d7118bbd4b1aa3edc18d69bb906d9e65f00700aad9cb3 index.html
a331d51864743ebe4e00dd22360b4a538b6b3ac26a6b3eb54094e60a36959a12 legal/PrivacyInfo.xcprivacy
13f929aae013a42408dd4e95cc6d42947b344a01c36292a58c804c708b370619 legal/privacy-policy.md
891b9cef0cc799c9dddf595afa763093ee0cfc46becba5d58ea1e9d206d367ed legal/terms-of-use.md
07f2891f660a425b5e1136173133d1cd13443f9c46ef3b581b511f608a5f36b4 marketing/brand-guide.md
d50904cccdcc439f340aff7253d561c350dcb88947389ac5abee14db7fa8c8b5 marketing/contact-sheet-ipad-13.jpg
2300f54d1f697d329022cb942bb97e88c338d0c844e9d14bb2bf5eaea4db5aa8 marketing/contact-sheet-iphone-6.9.jpg
34af26c9b1d9fa91ea5ff43fd264129df874583aaf961bea9ec38ea7ca1aa29b marketing/press-header.png
9880f405de5b4ca628c0042d62b18b7388bc136fbc5e4541ab94237965fa3a20 marketing/social-landscape.png
ddca648c4c88fbc726307241e05880b5c0d94329df22b728b6b45e1bd1ad081d marketing/social-square.png
350c55e38678eaf972ff653007ddcf67eb17354b15aa56cb51383fa873b7d8fc metadata/en-GB/description.txt
da3d8b42e6767a202975ab3acc35ab8840d4e13bcaa0a5901f94ff1a54dc72a0 metadata/en-GB/keywords.txt
f8c26eae41d0601da204abe258342ee34400599b47f437e77168a6864f13e621 metadata/en-GB/name.txt
32604bff19071ee403f69b81bad430af9069dbb60c4422305a648a6fda891825 metadata/en-GB/promotional_text.txt
8a2dac92364607cbc829d397addc9f6725dfa939b0a1f39d032693a640114bb8 metadata/en-GB/release_notes.txt
abb964f8c8c960cbfbdc12559cd5c1a9c015f1e370cbc9f80f74a6bb18609a98 metadata/en-GB/subtitle.txt
350c55e38678eaf972ff653007ddcf67eb17354b15aa56cb51383fa873b7d8fc metadata/en-US/description.txt
da3d8b42e6767a202975ab3acc35ab8840d4e13bcaa0a5901f94ff1a54dc72a0 metadata/en-US/keywords.txt
f8c26eae41d0601da204abe258342ee34400599b47f437e77168a6864f13e621 metadata/en-US/name.txt
32604bff19071ee403f69b81bad430af9069dbb60c4422305a648a6fda891825 metadata/en-US/promotional_text.txt
8a2dac92364607cbc829d397addc9f6725dfa939b0a1f39d032693a640114bb8 metadata/en-US/release_notes.txt
abb964f8c8c960cbfbdc12559cd5c1a9c015f1e370cbc9f80f74a6bb18609a98 metadata/en-US/subtitle.txt
846ef7bd0c544289a9cc557570a90e40b546cbe08081c331098e94901c4080b4 previews/Tarnax-ipad-13-poster.png
91d7857e4b1e278f40b179109e49c9e81d8b5bc77ac72095699f1385eba36d13 previews/Tarnax-ipad-13-preview.mp4
3c912b3e563ffba5d684efc2850fbc2f3d93fc2e47cc0a2c38b49f68074c747b previews/Tarnax-iphone-6.9-poster.png
bad1bed9c0d189a5e0083e790e225f644a7540a148a767e1f94b4106d958c08b previews/Tarnax-iphone-6.9-preview.mp4
6e643c2736ed9fe2d10654c2a4238761b5c68a51125c4d4713ba6198c3276910 previews/preview-info.json
050237c08cc0a9c9dcca3ff9c5acbff1c8e5ad0f2df0dd4743e13152ac101315 release-config.json
f61ea210a854c21882064bb8d77ebf034635a4ccf927e8fd9961311245854d23 review/age-rating-and-compliance.md
231309841c54f8bfdb69498b17e1e5d8a7e186dc7d1ac230615854ea2d17c9c2 review/privacy-label-assessment.md
7bb449344015bed537e4d76f9d03a404c7e580ad8c39d5fe25d97d879a0abf67 review/release-checklist.md
38960e34592cdce7c462e1257074ac5c052e36be1b48453d70513eb2216b0a2a review/review-notes.txt
450dc35958ad9eabcf36a7bf5acf6b5878f986a74fc07678c28b59dff6dd9a67 review/reviewer-access-checklist.md
595994544ddd1a03c5b238f5103dd9c10b427d4d19db53e98a3a861fb861b311 screenshots/raw/ipad-13/01-home.png
bd427c6f416c37bb300d798774384bbcd3ecabe10fc0ede3837433f03eb2fb15 screenshots/raw/ipad-13/02-library.png
7e9bb3deb1444024f6f145a2a4df70557655ccf3ac34bfaab76e5ed93bc25619 screenshots/raw/ipad-13/03-details.png
33920fb8f42f18c5eaf737c810cf645ee3446ed6205d5a272c0368fcde0d2707 screenshots/raw/ipad-13/04-files.png
40af107fa83aacc283508e30294a7ace6fec5a18e9f4c6ee82717f342b6b112e screenshots/raw/ipad-13/05-settings.png
47d40a830c309dd82176dfb808ac502d5ec01f36ae9cd4c86d748b5678259cce screenshots/raw/ipad-13/06-add.png
fcb7b8f98e1b5e11c9e1ce18c00532d6a4130c7d6e85c0b43139a9c3b06e444e screenshots/raw/iphone-6.9/01-home.png
fefcc73bc2c2770215aa3ae103b3f301d8a38104923896d44500cd6efaa7e68f screenshots/raw/iphone-6.9/02-library.png
8a716a7aeae5f9ec82cd952d4722219273f307c3658744196a024e7ecdfbeb23 screenshots/raw/iphone-6.9/03-details.png
06ab8baccbe55e489444814a93ab92a5462bb664f8b571e0532b3433615a679c screenshots/raw/iphone-6.9/04-files.png
5403182e93711055dd7144268cff0f961de29555c32f88d644027f2d9477e0b8 screenshots/raw/iphone-6.9/05-settings.png
ac2a2568e6657e04b4e4a8f24f3eba223a9595fe8595bf94eeef195e471a992e screenshots/raw/iphone-6.9/06-add.png
b2bc45c894c16c693f9f4b52b54d81df8d1eff804b189cb20a5db46699036198 screenshots/upload/ipad-13/01-home.png
a51b20bba01b2965e131b74c874f8505aef9e40dfdfe322f6b0679bb70f3ae93 screenshots/upload/ipad-13/02-library.png
3e9bd5c768daa4f2a10a350fa1d55e28774fd9f9b78611e14516b8ba54300113 screenshots/upload/ipad-13/03-details.png
61c4782fb82161f050b6fa4d2171643d3dfb3be16248b0c36869a600fc1a89de screenshots/upload/ipad-13/04-files.png
7de031bf40b4ac3d6243c8328b555c9c6dc44653410e9975b623d1586cd02a8d screenshots/upload/ipad-13/05-settings.png
e0086af28c11c093e586203e5ba626feeee6435d16d9782777388b42d5041314 screenshots/upload/ipad-13/06-add.png
ed387b7c406ab0b365c43a3d5784a3a52c3533673a283fe04ef22a7eebe44658 screenshots/upload/iphone-6.9/01-home.png
00de403541a7b5412a5500703871253a94068c58a067c15e55871791757eb328 screenshots/upload/iphone-6.9/02-library.png
304c9066091a7377616478f846c0f2e851e17669fd5975e15b42dab52c3a7c20 screenshots/upload/iphone-6.9/03-details.png
48052e33ce3d520826c0266ec0264b5471d5b9294f56e98a7de0ce65a10909c3 screenshots/upload/iphone-6.9/04-files.png
87f6036a9f87805c4ce13681d3d679e4769d0618d1ddbed544692d34cd9623ae screenshots/upload/iphone-6.9/05-settings.png
ca06430586c526e8453835552d17c8a8ef17f9953c66ec122ca2da97156e4973 screenshots/upload/iphone-6.9/06-add.png
9ed251947a2028763d621b0796537bf5011f7955546473318faa737adebfc17e tools/CaptureFixture.swift
e86300304dc94bcee8076482fe603881057d128e8f73b3097477f0c67866911f tools/archive.sh
970cc2141d288e56ae21bb912ad20f790978ef59a63edd9024d5117354dc6fca tools/build_website.py
a879d89dbfedfc14cb4fa86234b0d7687326c26d80e37d1fed6756c8e5096bc7 tools/capture.sh
abc9418074ad8374b0217c95028eb3711650efbf6e2e1b0c7ef86aa0b8226b63 tools/make_previews.py
898a545d2ea544c59b039722358db146353820dec97017011ed1eeb5b8742da1 tools/prepare_capture.py
c8a598609e773aaebe248a6c806ee9fbaf2eb02d350e7fac6cde7a84d6b73516 tools/render_assets.py
d3d0e25991e5570c636f9fc33b511ad01f4a11496cf97cfaf0f0e1d7679d52a1 tools/validate.py
ad7fef1fc3c6fd01cc605fb71df0e3def7a66bb1be010c6ed1e700d350224c86 validation-report.json
51b1b1f9b03f020f9f9c18972e6340622a147e104cc1b2766516807d5243e604 validation-report.md
8eccf035da8692920262e9f917b6f2971f9a9386a0125d773fb778a53367e0ed website/assets/apple-touch-icon.png
283777a7ae895a7e6f0dc0b76c17597eec98d522ed8564eac48bc88aa466d1e3 website/assets/favicon.png
0dd661c392e1704bdbf1b34db1a32ec5c1f063d5f8565f84d0df69b8383e0e19 website/assets/icon.png
9880f405de5b4ca628c0042d62b18b7388bc136fbc5e4541ab94237965fa3a20 website/assets/social.png
171ee36f6052e1651681bc383237959900c97250e3514f7ead2f16cb010ebe70 website/index.html
41a9fb5fdc154cc5799b93bf5e65b2ef59e8ec2a0d4116b5cd9508a4fc8a41c5 website/privacy.html
923d3cdc5124247f7d762f94b76264706555c2d37851b15440d1e91495ade839 website/style.css
dc6cd7757303bc171cd38023c10a8e290817c12d4543ca994df818af38af9943 website/support.html
e0e5f7b25d9e0239ac7d280f403b8a0ec2be9167edbe9e4280e1f7efd7dc0e34 website/terms.html
+1
View File
@@ -0,0 +1 @@
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Tarnax release assets</title><style>body{margin:40px;background:#0b1020;color:#eef2ff;font:16px system-ui}a{color:#a5b4fc}main{max-width:1300px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:24px}figure{margin:0}img{width:100%;height:auto;border-radius:12px}nav{display:flex;gap:20px;flex-wrap:wrap;margin:30px 0}video{max-width:300px;max-height:600px}</style><main><h1>Tarnax</h1><p>App Store release assets · Version 1.0 (8)</p><p>Prepared locally. Website URLs, reviewer access and signing must be completed before submission.</p><nav><a href="README.md">Instructions</a><a href="validation-report.md">Validation</a><a href="website/index.html">Website</a><a href="review/release-checklist.md">Release checklist</a><a href="metadata/en-GB/description.txt">Store description</a></nav><h2>Screenshots</h2><div class="grid"><figure><a href="screenshots/upload/iphone-6.9/01-home.png"><img src="screenshots/upload/iphone-6.9/01-home.png" alt="01-home screenshot"></a><figcaption>iphone-6.9 · 01-home</figcaption></figure><figure><a href="screenshots/upload/iphone-6.9/02-library.png"><img src="screenshots/upload/iphone-6.9/02-library.png" alt="02-library screenshot"></a><figcaption>iphone-6.9 · 02-library</figcaption></figure><figure><a href="screenshots/upload/iphone-6.9/03-details.png"><img src="screenshots/upload/iphone-6.9/03-details.png" alt="03-details screenshot"></a><figcaption>iphone-6.9 · 03-details</figcaption></figure><figure><a href="screenshots/upload/iphone-6.9/04-files.png"><img src="screenshots/upload/iphone-6.9/04-files.png" alt="04-files screenshot"></a><figcaption>iphone-6.9 · 04-files</figcaption></figure><figure><a href="screenshots/upload/iphone-6.9/05-settings.png"><img src="screenshots/upload/iphone-6.9/05-settings.png" alt="05-settings screenshot"></a><figcaption>iphone-6.9 · 05-settings</figcaption></figure><figure><a href="screenshots/upload/iphone-6.9/06-add.png"><img src="screenshots/upload/iphone-6.9/06-add.png" alt="06-add screenshot"></a><figcaption>iphone-6.9 · 06-add</figcaption></figure><figure><a href="screenshots/upload/ipad-13/01-home.png"><img src="screenshots/upload/ipad-13/01-home.png" alt="01-home screenshot"></a><figcaption>ipad-13 · 01-home</figcaption></figure><figure><a href="screenshots/upload/ipad-13/02-library.png"><img src="screenshots/upload/ipad-13/02-library.png" alt="02-library screenshot"></a><figcaption>ipad-13 · 02-library</figcaption></figure><figure><a href="screenshots/upload/ipad-13/03-details.png"><img src="screenshots/upload/ipad-13/03-details.png" alt="03-details screenshot"></a><figcaption>ipad-13 · 03-details</figcaption></figure><figure><a href="screenshots/upload/ipad-13/04-files.png"><img src="screenshots/upload/ipad-13/04-files.png" alt="04-files screenshot"></a><figcaption>ipad-13 · 04-files</figcaption></figure><figure><a href="screenshots/upload/ipad-13/05-settings.png"><img src="screenshots/upload/ipad-13/05-settings.png" alt="05-settings screenshot"></a><figcaption>ipad-13 · 05-settings</figcaption></figure><figure><a href="screenshots/upload/ipad-13/06-add.png"><img src="screenshots/upload/ipad-13/06-add.png" alt="06-add screenshot"></a><figcaption>ipad-13 · 06-add</figcaption></figure></div><h2>Optional previews</h2><video controls preload="metadata" src="previews/Tarnax-iphone-6.9-preview.mp4"></video> <video controls preload="metadata" src="previews/Tarnax-ipad-13-preview.mp4"></video></main></html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
[
{
"file": "previews/Tarnax-iphone-6.9-preview.mp4",
"width": 886,
"height": 1920,
"duration_seconds": 24,
"fps": 30,
"codec": "H.264 High Level 4.0",
"audio": "AAC stereo 48kHz, silent",
"poster_frame_seconds": 1,
"footage": "Actual app UI captured in a simulator with fictitious sample data; no marketing artwork inserted."
},
{
"file": "previews/Tarnax-ipad-13-preview.mp4",
"width": 1200,
"height": 1600,
"duration_seconds": 24,
"fps": 30,
"codec": "H.264 High Level 4.0",
"audio": "AAC stereo 48kHz, silent",
"poster_frame_seconds": 1,
"footage": "Actual app UI captured in a simulator with fictitious sample data; no marketing artwork inserted."
}
]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 481 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 KiB

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 KiB

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 KiB

After

Width:  |  Height:  |  Size: 449 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 KiB

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 KiB

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 KiB

After

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 242 KiB

+55
View File
@@ -0,0 +1,55 @@
#!/bin/bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT/scripts/common.sh"
PROVISIONING=()
case "${1:-}" in
--allow-provisioning-updates) PROVISIONING=(-allowProvisioningUpdates) ;;
'') ;;
-h|--help) echo 'Usage: appstore/tools/archive.sh [--allow-provisioning-updates]'; echo 'Creates an App Store archive and locally exports an IPA. Never uploads.'; exit 0 ;;
*) echo "Unknown option: $1" >&2; exit 2 ;;
esac
[[ $# -le 1 ]] || { echo 'Too many arguments' >&2; exit 2; }
OUTPUT="$(mktemp -d "$ROOT/appstore/build/$(date +%Y%m%d-%H%M%S).XXXXXX")"
DERIVED="$(mktemp -d "$TARNAX_SCRATCH_ROOT/appstore-derived.XXXXXX")"
echo "Output: $OUTPUT"
xcodebuild -project "$ROOT/Tarnax.xcodeproj" -scheme Tarnax -configuration Release \
-destination 'generic/platform=iOS' -derivedDataPath "$DERIVED" \
-archivePath "$OUTPUT/Tarnax.xcarchive" \
${PROVISIONING[@]+"${PROVISIONING[@]}"} archive 2>&1 | tee "$OUTPUT/archive.log"
APP="$OUTPUT/Tarnax.xcarchive/Products/Applications/Tarnax.app"
[[ -f "$APP/PrivacyInfo.xcprivacy" ]] || { echo 'Privacy manifest missing from archive' >&2; exit 1; }
plutil -lint "$APP/PrivacyInfo.xcprivacy"
xcrun nm -m "$APP/Tarnax" > "$DERIVED/symbols.txt"
if grep -E 'weak external.*Foundation4DateV2(ge|le)oiy' "$DERIVED/symbols.txt"; then
echo 'Incompatible Foundation Date comparison entry point detected' >&2; exit 1
fi
if grep -E 'StoreCapture|CaptureFixture' "$DERIVED/symbols.txt"; then
echo 'Screenshot fixture leaked into production archive' >&2; exit 1
fi
xcodebuild -exportArchive -archivePath "$OUTPUT/Tarnax.xcarchive" \
-exportPath "$OUTPUT/export" -exportOptionsPlist "$ROOT/appstore/build/ExportOptions-AppStore.plist" \
${PROVISIONING[@]+"${PROVISIONING[@]}"} 2>&1 | tee "$OUTPUT/export.log"
[[ -f "$OUTPUT/export/Tarnax.ipa" ]] || { echo 'IPA export missing' >&2; exit 1; }
VERIFY="$(mktemp -d "$TARNAX_SCRATCH_ROOT/appstore-verify.XXXXXX")"
trap 'rm -rf "$VERIFY"' EXIT
unzip -q "$OUTPUT/export/Tarnax.ipa" -d "$VERIFY"
codesign --verify --deep --strict "$VERIFY/Payload/Tarnax.app"
security cms -D -i "$VERIFY/Payload/Tarnax.app/embedded.mobileprovision" > "$VERIFY/profile.plist"
python3 - "$VERIFY" "$ROOT/appstore/build/latest.json" "$OUTPUT" <<'PY'
from pathlib import Path
import json,plistlib,sys,hashlib,datetime
root=Path(sys.argv[1]);app=root/'Payload/Tarnax.app'
with (app/'Info.plist').open('rb') as f:info=plistlib.load(f)
with (root/'profile.plist').open('rb') as f:profile=plistlib.load(f)
assert info['CFBundleIdentifier']=='net.absdev.Tarnax'
assert not profile.get('ProvisionedDevices'), 'Device-limited profile is not App Store distribution'
assert not profile.get('ProvisionsAllDevices'), 'Enterprise profile is not App Store distribution'
assert not profile['Entitlements'].get('get-task-allow',False), 'Debugging enabled'
assert profile['ExpirationDate']>datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
output=Path(sys.argv[3]);ipa=output/'export/Tarnax.ipa'
checksum=hashlib.sha256(ipa.read_bytes()).hexdigest()
(output/'export/Tarnax.ipa.sha256').write_text(checksum+' Tarnax.ipa\n')
Path(sys.argv[2]).write_text(json.dumps({'version':info['CFBundleShortVersionString'],'build':info['CFBundleVersion'],'archive':str(output/'Tarnax.xcarchive'),'ipa':str(ipa),'sha256':checksum,'distribution':'app-store-connect','uploaded':False},indent=2)+'\n')
print('Verified App Store IPA:',ipa)
PY
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Build static, tracker-free support and policy pages ready for HTTPS hosting."""
from pathlib import Path
import html,re
ROOT=Path(__file__).resolve().parents[1]
SITE=ROOT/'website'
def markdown(text):
blocks=[];inlist=False
for line in text.splitlines():
if not line.strip():
if inlist:blocks.append('</ul>');inlist=False
continue
line=html.escape(line)
line=re.sub(r'(https://[^\s<]+)',r'<a href="\1">\1</a>',line)
if line.startswith('# '):blocks.append('<h1>'+line[2:]+'</h1>')
elif line.startswith('## '):blocks.append('<h2>'+line[3:]+'</h2>')
elif line.startswith('- '):
if not inlist:blocks.append('<ul>');inlist=True
blocks.append('<li>'+line[2:]+'</li>')
else:blocks.append('<p>'+line+'</p>')
if inlist:blocks.append('</ul>')
return '\n'.join(blocks)
def page(title,content):
return '''<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Tarnax — native remote control for your qBittorrent server. Support and privacy information."><title>'''+html.escape(title)+''' · Tarnax</title><link rel="icon" href="assets/favicon.png"><link rel="apple-touch-icon" href="assets/apple-touch-icon.png"><link rel="stylesheet" href="style.css"></head><body><header><a class="brand" href="index.html"><img src="assets/icon.png" alt="" width="44" height="44">Tarnax</a><nav aria-label="Main navigation"><a href="support.html">Support</a><a href="privacy.html">Privacy</a><a href="terms.html">Usage</a></nav></header><main>'''+content+'''</main><footer>© 2026 Mark Gregory · <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a><p>Independent software. Not affiliated with or endorsed by the qBittorrent project.</p></footer></body></html>'''
SITE.mkdir(exist_ok=True)
SITE.joinpath('style.css').write_text('''*{box-sizing:border-box}html{color-scheme:dark}body{margin:0;background:#070b1b;color:#edf1fc;font:18px/1.7 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}header,main,footer{max-width:1060px;margin:auto;padding:30px clamp(20px,5vw,64px)}header{display:flex;justify-content:space-between;align-items:center;gap:20px;border-bottom:1px solid #242e4a}.brand{display:flex;align-items:center;gap:14px;color:white;font-size:25px;font-weight:700;text-decoration:none}.brand img{border-radius:10px}nav{display:flex;gap:24px}a{color:#a9bdff;text-underline-offset:4px}a:hover{color:#fff}a:focus-visible{outline:3px solid #25c7ce;outline-offset:6px}h1{font-size:clamp(36px,6vw,64px);line-height:1.12;letter-spacing:-1.8px;margin:30px 0}h2{font-size:26px;line-height:1.3;margin-top:45px}p,li{max-width:76ch;color:#c8d2e8}.eyebrow{color:#67e3dd;font-size:14px;font-weight:700;letter-spacing:2px;text-transform:uppercase}.hero{padding:30px 0 50px}.hero img{width:140px;border-radius:32px}.hero strong{color:#c0c9ff}.button{display:inline-block;background:#7763ff;color:white;text-decoration:none;padding:12px 23px;border-radius:12px;font-weight:650}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px}.card{background:#111a31;border:1px solid #253253;border-radius:20px;padding:25px}.card h2{margin-top:0}.note{padding:20px 25px;border-left:3px solid #20bdc4;background:#101b2d}footer{font-size:14px;border-top:1px solid #242e4a;margin-top:40px}footer p{font-size:13px}details{border-bottom:1px solid #253253;padding:20px 0}summary{cursor:pointer;font-weight:650;color:white}@media(max-width:600px){header{align-items:flex-start;flex-direction:column}nav{font-size:16px}body{font-size:17px}}''')
home='''<section class="hero"><img src="assets/icon.png" alt="Tarnax app icon"><p class="eyebrow">Remote for qBittorrent</p><h1>Your server.<br><strong>Your control.</strong></h1><p>A native iPhone and iPad remote for your own qBittorrent server. Follow live transfers, organise your library and manage the details from wherever you are.</p><a class="button" href="support.html">Get support</a></section><section class="cards"><article class="card"><h2>See the flow</h2><p>Colourful upload and download graphs, live speeds and the server space you need to know about.</p></article><article class="card"><h2>Manage the details</h2><p>Search and filter your transfers, control file priorities and edit your server’s preferences.</p></article><article class="card"><h2>Your connection</h2><p>Trusted HTTPS, device Keychain credentials and optional Face ID or device authentication.</p></article></section><p class="note">Requires your own qBittorrent server with its Web UI API enabled and a trusted HTTPS connection. Torrent contents stay on your server. Use only content you are authorised to access and share.</p>'''
SITE.joinpath('index.html').write_text(page('Your server. Your control.',home))
support='''<h1>How can we help?</h1><p>For Tarnax support, email <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a>. Please include the Tarnax version/build, iPhone or iPad model, iOS version, qBittorrent version, and what happened.</p><p class="note">Never send passwords, private magnet links or sensitive server contents. Redact identifying information from screenshots.</p><h2>Quick answers</h2>'''
faqs=[('What do I need?','An existing qBittorrent server, Web UI API access, valid credentials and a trusted HTTPS endpoint. Tarnax does not provide the server, content catalogue or a VPN.'),('Why does my connection fail?','Check the HTTPS hostname, certificate chain and reverse-proxy subpath. HTTP 401 usually means proxy authentication; HTTP 403 may indicate session expiry, access rules or server protection. Use Disconnect/change server to reconnect after correcting the configuration.'),('Does Tarnax download to my phone?','No. It sends commands and selected .torrent files to your server. Torrent contents remain on that server.'),('Why does the graph start empty?','History records transfer samples while Tarnax is active and unlocked. It is session history, not a download-history database. Wait for a few updates; background pauses appear as gaps.'),('How do I retry Face ID?','Normal unlocking happens automatically. If authentication is cancelled or interrupted, tap Unlock to retry using Face ID or the device passcode fallback. Check that the app is allowed to use Face ID in iOS Settings.'),('How do I remove saved credentials?','Open Tarnax Settings and choose Forget saved credentials. iOS may retain Keychain data after deleting an app, so use this action before uninstalling if you want to remove the saved connection.'),('Can I edit every server option?','Tarnax exposes preferences returned by your server. Available settings and commands depend on qBittorrent’s version and configuration. Network, authentication and storage changes may interrupt access or move data.'),('Why don’t transfers update in the background?','This version refreshes while the app is active and unlocked. iOS background execution is not requested.'),('Where is the privacy policy?','Open Privacy in the navigation above, or Settings → Privacy policy inside Tarnax.')]
for q,a in faqs:support+='<details><summary>'+html.escape(q)+'</summary><p>'+html.escape(a)+'</p></details>'
SITE.joinpath('support.html').write_text(page('Support',support))
privacy=markdown((ROOT/'legal/privacy-policy.md').read_text())+'<h2>This website</h2><p>These supplied pages contain no analytics scripts, advertising or cookies. The hosting provider you use may process technical request logs for operating and securing the site. Confirm the final hosting arrangement before publishing this policy.</p>'
SITE.joinpath('privacy.html').write_text(page('Privacy',privacy))
SITE.joinpath('terms.html').write_text(page('Usage',markdown((ROOT/'legal/terms-of-use.md').read_text())))
print('Built four static support/marketing/policy pages; no publication performed.')
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
"""Create 24-second previews solely from actual simulator screen-recording footage."""
from pathlib import Path
import json,subprocess,os
ROOT=Path(__file__).resolve().parents[1]
SCRATCH=Path(os.environ.get('TARNAX_SCRATCH_ROOT',str(Path.home()/'Developer/Scratch/Tarnax')))
SCENES=['01-home','02-library','03-details','04-files','05-settings','06-add']
metadata=[]
for device,size in [('iphone-6.9',(886,1920)),('ipad-13',(1200,1600))]:
w,h=size
work=SCRATCH/'appstore-video'/device
encoded=[]
for scene in SCENES:
src=work/(scene+'.mov');out=work/(scene+'-encoded.mp4')
vf=f'tpad=stop_mode=clone:stop_duration=4,scale={w}:{h}:force_original_aspect_ratio=decrease:force_divisible_by=2,pad={w}:{h}:(ow-iw)/2:(oh-ih)/2:color=black,fps=30,setsar=1,format=yuv420p'
cmd=['ffmpeg','-y','-v','error','-ss','0','-i',str(src),'-f','lavfi','-i','anullsrc=r=48000:cl=stereo','-t','4','-vf',vf,'-c:v','libx264','-preset','fast','-profile:v','high','-level:v','4.0','-b:v','10M','-maxrate','12M','-bufsize','20M','-pix_fmt','yuv420p','-color_primaries','bt709','-color_trc','bt709','-colorspace','bt709','-c:a','aac','-b:a','256k','-ar','48000','-ac','2','-movflags','+faststart',str(out)]
subprocess.run(cmd,check=True);encoded.append(out)
playlist=work/'concat.txt';playlist.write_text(''.join("file '"+str(p).replace("'","'\\''")+"'\n" for p in encoded))
dst=ROOT/f'previews/Tarnax-{device}-preview.mp4'
subprocess.run(['ffmpeg','-y','-v','error','-f','concat','-safe','0','-i',str(playlist),'-c','copy','-movflags','+faststart',str(dst)],check=True)
poster=ROOT/f'previews/Tarnax-{device}-poster.png'
subprocess.run(['ffmpeg','-y','-v','error','-ss','1','-i',str(dst),'-frames:v','1',str(poster)],check=True)
metadata.append({'file':str(dst.relative_to(ROOT)),'width':w,'height':h,'duration_seconds':24,'fps':30,'codec':'H.264 High Level 4.0','audio':'AAC stereo 48kHz, silent','poster_frame_seconds':1,'footage':'Actual app UI captured in a simulator with fictitious sample data; no marketing artwork inserted.'})
(ROOT/'previews/preview-info.json').write_text(json.dumps(metadata,indent=2)+'\n')
print('Created iPhone and iPad 24-second App Preview files.')
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
"""Validate local release assets; use --submission-ready to require owner setup too."""
from pathlib import Path
from PIL import Image,ImageStat
import json,subprocess,plistlib,hashlib,sys
R=Path(__file__).resolve().parents[1]
errors=[];checks=[]
def check(ok,label):
(checks if ok else errors).append(label)
for locale in ['en-GB','en-US']:
for name,limit in [('name',30),('subtitle',30),('promotional_text',170),('description',4000),('keywords',100)]:
value=(R/f'metadata/{locale}/{name}.txt').read_text().strip()
check(bool(value) and (len(value.encode()) if name=='keywords' else len(value))<=limit,f'{locale}/{name}: length within {limit}')
manifest=json.loads((R/'asset-manifest.json').read_text())
check(len(manifest['screenshots'])==12,'12 upload screenshots')
for item in manifest['screenshots']:
for name in [item['file'],item['source']]:
im=Image.open(R/name)
check(im.size==(item['width'],item['height']) and (im.mode=='RGB' or ('A' in im.getbands() and im.getchannel('A').getextrema()==(255,255))),f'{name}: dimensions and opacity')
check(max(ImageStat.Stat(im.resize((100,100))).stddev)>15,f'{name}: nonblank image')
im=Image.open(R/'icons/Tarnax-AppStore-1024.png')
check(im.size==(1024,1024) and im.mode=='RGB','App Store icon: opaque 1024 square')
for device,size in [('iphone-6.9',(886,1920)),('ipad-13',(1200,1600))]:
file=R/f'previews/Tarnax-{device}-preview.mp4'
if not file.exists(): check(False,f'{device}: preview exists');continue
data=json.loads(subprocess.check_output(['ffprobe','-v','error','-show_streams','-show_format','-of','json',str(file)]))
video=next((s for s in data['streams'] if s['codec_type']=='video'),{})
audio=next((s for s in data['streams'] if s['codec_type']=='audio'),{})
check((video.get('width'),video.get('height'))==size and video.get('codec_name')=='h264' and video.get('level',999)<=40,f'{device}: video format')
check(15<=float(data['format']['duration'])<=30 and file.stat().st_size<500_000_000,f'{device}: duration and size')
check(audio.get('codec_name')=='aac' and audio.get('channels')==2 and audio.get('sample_rate')=='48000',f'{device}: audio format')
a=plistlib.loads((R/'legal/PrivacyInfo.xcprivacy').read_bytes())
check(a==plistlib.loads((R.parent/'Tarnax/PrivacyInfo.xcprivacy').read_bytes()),'Privacy manifest matches shipping source')
for name in ['index.html','support.html','privacy.html','terms.html','style.css']:
check((R/'website'/name).exists(),f'Website {name}')
config=json.loads((R/'release-config.json').read_text())
owner=[key for key in ['support_url','privacy_policy_url','price','territories'] if config[key] is None]
if not config['review_contact']['phone']:owner.append('review contact phone')
if not config['review_server']['https_url']:owner.append('dedicated reviewer server and credentials')
if not (R/'build/latest.json').exists():owner.append('App Store signed IPA export')
owner+=['Confirm naming rights, privacy answers, age rating, agreements and final physical-device QA']
report={'asset_checks_passed':len(checks),'asset_errors':errors,'submission_ready':not(errors or owner),'owner_actions':owner}
(R/'validation-report.json').write_text(json.dumps(report,indent=2)+'\n')
(R/'validation-report.md').write_text('# Release asset validation\n\n'+f'{len(checks)} checks passed. {len(errors)} asset errors.\n\n'+ '\n'.join('- '+v for v in errors)+'\n\n## Owner actions before submission\n\n'+'\n'.join('- '+v for v in owner)+'\n')
files=sorted(p for p in R.rglob('*') if p.is_file() and 'build' not in p.relative_to(R).parts and p.name not in ['SHA256SUMS'] and '__pycache__' not in p.parts)
(R/'SHA256SUMS').write_text(''.join(hashlib.sha256(p.read_bytes()).hexdigest()+' '+str(p.relative_to(R))+'\n' for p in files))
print(json.dumps(report,indent=2))
sys.exit(1 if errors else 2 if '--submission-ready' in sys.argv and owner else 0)
+15
View File
@@ -0,0 +1,15 @@
{
"asset_checks_passed": 72,
"asset_errors": [],
"submission_ready": false,
"owner_actions": [
"support_url",
"privacy_policy_url",
"price",
"territories",
"review contact phone",
"dedicated reviewer server and credentials",
"App Store signed IPA export",
"Confirm naming rights, privacy answers, age rating, agreements and final physical-device QA"
]
}
+16
View File
@@ -0,0 +1,16 @@
# Release asset validation
72 checks passed. 0 asset errors.
## Owner actions before submission
- support_url
- privacy_policy_url
- price
- territories
- review contact phone
- dedicated reviewer server and credentials
- App Store signed IPA export
- Confirm naming rights, privacy answers, age rating, agreements and final physical-device QA
Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 148 KiB

+1
View File
@@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Tarnax — native remote control for your qBittorrent server. Support and privacy information."><title>Your server. Your control. · Tarnax</title><link rel="icon" href="assets/favicon.png"><link rel="apple-touch-icon" href="assets/apple-touch-icon.png"><link rel="stylesheet" href="style.css"></head><body><header><a class="brand" href="index.html"><img src="assets/icon.png" alt="" width="44" height="44">Tarnax</a><nav aria-label="Main navigation"><a href="support.html">Support</a><a href="privacy.html">Privacy</a><a href="terms.html">Usage</a></nav></header><main><section class="hero"><img src="assets/icon.png" alt="Tarnax app icon"><p class="eyebrow">Remote for qBittorrent</p><h1>Your server.<br><strong>Your control.</strong></h1><p>A native iPhone and iPad remote for your own qBittorrent server. Follow live transfers, organise your library and manage the details from wherever you are.</p><a class="button" href="support.html">Get support</a></section><section class="cards"><article class="card"><h2>See the flow</h2><p>Colourful upload and download graphs, live speeds and the server space you need to know about.</p></article><article class="card"><h2>Manage the details</h2><p>Search and filter your transfers, control file priorities and edit your server’s preferences.</p></article><article class="card"><h2>Your connection</h2><p>Trusted HTTPS, device Keychain credentials and optional Face ID or device authentication.</p></article></section><p class="note">Requires your own qBittorrent server with its Web UI API enabled and a trusted HTTPS connection. Torrent contents stay on your server. Use only content you are authorised to access and share.</p></main><footer>© 2026 Mark Gregory · <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a><p>Independent software. Not affiliated with or endorsed by the qBittorrent project.</p></footer></body></html>
+21
View File
@@ -0,0 +1,21 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Tarnax — native remote control for your qBittorrent server. Support and privacy information."><title>Privacy · Tarnax</title><link rel="icon" href="assets/favicon.png"><link rel="apple-touch-icon" href="assets/apple-touch-icon.png"><link rel="stylesheet" href="style.css"></head><body><header><a class="brand" href="index.html"><img src="assets/icon.png" alt="" width="44" height="44">Tarnax</a><nav aria-label="Main navigation"><a href="support.html">Support</a><a href="privacy.html">Privacy</a><a href="terms.html">Usage</a></nav></header><main><h1>Tarnax privacy policy</h1>
<p>Effective date: 4 November 2026</p>
<p>Tarnax is developed by Mark Gregory. Contact: mark.gregory@abbeysoftware.com.</p>
<h2>Your connection</h2>
<p>Tarnax is a remote control for a qBittorrent server that you configure. It sends your server address, authentication information, API requests, torrent links or files that you choose to add, and management commands directly to that server over HTTPS. Reverse-proxy credentials, if configured, are sent to the proxy serving that connection. The server and proxy operators may retain access logs, IP addresses, account information or transfer data under their own policies. You are responsible for choosing a server you trust and having permission to use it.</p>
<p>Tarnax does not provide a hosted torrent service. It does not send your library or credentials to a developer-operated service unless you explicitly choose a server operated by the developer. The released app has no preset production server.</p>
<h2>Information on your device</h2>
<p>Saved connection credentials are kept in the device Keychain with device-only, when-unlocked protection. The app-lock preference and navigation state are stored locally. Session cookies use a private temporary network session and are discarded when the connection closes. Transfer-history samples are held in memory for the current session and are cleared when the server connection is replaced or disconnected.</p>
<p>When you select a .torrent file, Tarnax reads it to upload it to your chosen server. Torrent contents remain on the server; Tarnax does not download those contents to your iPhone or iPad.</p>
<h2>Authentication</h2>
<p>Face ID, Touch ID where supported, and device passcode authentication are handled by Apple&#x27;s LocalAuthentication services. Tarnax receives an authentication result. It does not receive or store biometric templates, facial images or your device passcode.</p>
<h2>Tracking and analytics</h2>
<p>Tarnax includes no advertising, tracking SDKs or third-party analytics services. It does not request advertising identifiers, contacts, photos, microphone, camera or location access. Apple may process App Store, payment or diagnostic information according to your Apple settings and Apple&#x27;s policies. Information collected independently by your selected server is governed by that server operator.</p>
<h2>Support correspondence</h2>
<p>If you email support, we receive the information you choose to send and use it to respond, investigate the issue and maintain the support correspondence. Email providers process those messages as part of delivering the service. Do not send passwords, private torrent links or sensitive server data. Ask us to delete support correspondence by emailing the address above; we will consider the request subject to applicable retention obligations and legitimate record-keeping needs.</p>
<h2>Your choices</h2>
<p>Use Settings → Forget saved credentials to remove Tarnax&#x27;s saved Keychain credentials and disconnect. Disconnecting also discards the session history. Deleting the app removes its local app data, but iOS may retain Keychain items; use the Forget action before deleting the app if you want to remove those credentials. Server-side accounts, files, logs and torrent data must be managed with your server operator.</p>
<h2>Children and changes</h2>
<p>Tarnax is a general-purpose server utility and is not designed specifically for children. We do not knowingly seek personal information from children. This policy may be updated if the app or its data practices change. The effective date above identifies the current version.</p>
<h2>Contact</h2>
<p>mark.gregory@abbeysoftware.com</p><h2>This website</h2><p>These supplied pages contain no analytics scripts, advertising or cookies. The hosting provider you use may process technical request logs for operating and securing the site. Confirm the final hosting arrangement before publishing this policy.</p></main><footer>© 2026 Mark Gregory · <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a><p>Independent software. Not affiliated with or endorsed by the qBittorrent project.</p></footer></body></html>
+1
View File
@@ -0,0 +1 @@
*{box-sizing:border-box}html{color-scheme:dark}body{margin:0;background:#070b1b;color:#edf1fc;font:18px/1.7 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}header,main,footer{max-width:1060px;margin:auto;padding:30px clamp(20px,5vw,64px)}header{display:flex;justify-content:space-between;align-items:center;gap:20px;border-bottom:1px solid #242e4a}.brand{display:flex;align-items:center;gap:14px;color:white;font-size:25px;font-weight:700;text-decoration:none}.brand img{border-radius:10px}nav{display:flex;gap:24px}a{color:#a9bdff;text-underline-offset:4px}a:hover{color:#fff}a:focus-visible{outline:3px solid #25c7ce;outline-offset:6px}h1{font-size:clamp(36px,6vw,64px);line-height:1.12;letter-spacing:-1.8px;margin:30px 0}h2{font-size:26px;line-height:1.3;margin-top:45px}p,li{max-width:76ch;color:#c8d2e8}.eyebrow{color:#67e3dd;font-size:14px;font-weight:700;letter-spacing:2px;text-transform:uppercase}.hero{padding:30px 0 50px}.hero img{width:140px;border-radius:32px}.hero strong{color:#c0c9ff}.button{display:inline-block;background:#7763ff;color:white;text-decoration:none;padding:12px 23px;border-radius:12px;font-weight:650}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px}.card{background:#111a31;border:1px solid #253253;border-radius:20px;padding:25px}.card h2{margin-top:0}.note{padding:20px 25px;border-left:3px solid #20bdc4;background:#101b2d}footer{font-size:14px;border-top:1px solid #242e4a;margin-top:40px}footer p{font-size:13px}details{border-bottom:1px solid #253253;padding:20px 0}summary{cursor:pointer;font-weight:650;color:white}@media(max-width:600px){header{align-items:flex-start;flex-direction:column}nav{font-size:16px}body{font-size:17px}}
+1
View File
@@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Tarnax — native remote control for your qBittorrent server. Support and privacy information."><title>Support · Tarnax</title><link rel="icon" href="assets/favicon.png"><link rel="apple-touch-icon" href="assets/apple-touch-icon.png"><link rel="stylesheet" href="style.css"></head><body><header><a class="brand" href="index.html"><img src="assets/icon.png" alt="" width="44" height="44">Tarnax</a><nav aria-label="Main navigation"><a href="support.html">Support</a><a href="privacy.html">Privacy</a><a href="terms.html">Usage</a></nav></header><main><h1>How can we help?</h1><p>For Tarnax support, email <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a>. Please include the Tarnax version/build, iPhone or iPad model, iOS version, qBittorrent version, and what happened.</p><p class="note">Never send passwords, private magnet links or sensitive server contents. Redact identifying information from screenshots.</p><h2>Quick answers</h2><details><summary>What do I need?</summary><p>An existing qBittorrent server, Web UI API access, valid credentials and a trusted HTTPS endpoint. Tarnax does not provide the server, content catalogue or a VPN.</p></details><details><summary>Why does my connection fail?</summary><p>Check the HTTPS hostname, certificate chain and reverse-proxy subpath. HTTP 401 usually means proxy authentication; HTTP 403 may indicate session expiry, access rules or server protection. Use Disconnect/change server to reconnect after correcting the configuration.</p></details><details><summary>Does Tarnax download to my phone?</summary><p>No. It sends commands and selected .torrent files to your server. Torrent contents remain on that server.</p></details><details><summary>Why does the graph start empty?</summary><p>History records transfer samples while Tarnax is active and unlocked. It is session history, not a download-history database. Wait for a few updates; background pauses appear as gaps.</p></details><details><summary>How do I retry Face ID?</summary><p>Normal unlocking happens automatically. If authentication is cancelled or interrupted, tap Unlock to retry using Face ID or the device passcode fallback. Check that the app is allowed to use Face ID in iOS Settings.</p></details><details><summary>How do I remove saved credentials?</summary><p>Open Tarnax Settings and choose Forget saved credentials. iOS may retain Keychain data after deleting an app, so use this action before uninstalling if you want to remove the saved connection.</p></details><details><summary>Can I edit every server option?</summary><p>Tarnax exposes preferences returned by your server. Available settings and commands depend on qBittorrent’s version and configuration. Network, authentication and storage changes may interrupt access or move data.</p></details><details><summary>Why don’t transfers update in the background?</summary><p>This version refreshes while the app is active and unlocked. iOS background execution is not requested.</p></details><details><summary>Where is the privacy policy?</summary><p>Open Privacy in the navigation above, or Settings → Privacy policy inside Tarnax.</p></details></main><footer>© 2026 Mark Gregory · <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a><p>Independent software. Not affiliated with or endorsed by the qBittorrent project.</p></footer></body></html>
+7
View File
@@ -0,0 +1,7 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Tarnax — native remote control for your qBittorrent server. Support and privacy information."><title>Usage · Tarnax</title><link rel="icon" href="assets/favicon.png"><link rel="apple-touch-icon" href="assets/apple-touch-icon.png"><link rel="stylesheet" href="style.css"></head><body><header><a class="brand" href="index.html"><img src="assets/icon.png" alt="" width="44" height="44">Tarnax</a><nav aria-label="Main navigation"><a href="support.html">Support</a><a href="privacy.html">Privacy</a><a href="terms.html">Usage</a></nav></header><main><h1>Tarnax usage information</h1>
<p>Tarnax is an independent remote-control app for a user-configured qBittorrent server. It is not affiliated with or endorsed by the qBittorrent project, Marvel or any other software or entertainment brand.</p>
<p>You need permission to access the server and to access, download or share any content you manage through it. Tarnax does not provide a content catalogue, search service, hosted download account, VPN or cloud storage. Do not use it to infringe intellectual-property rights or other applicable laws.</p>
<p>Commands run on your server. Moving storage, changing server settings and deleting server files can have immediate effects. Keep backups and review destructive confirmations carefully. Feature availability depends on your server version and setup.</p>
<p>If distributed through Apple&#x27;s App Store without a custom licence, Apple&#x27;s Standard Licensed Application End User License Agreement applies, together with any mandatory local consumer rights. This usage page does not replace that agreement or limit rights that cannot lawfully be excluded.</p>
<p>Apple Standard EULA: <a href="https://www.apple.com/legal/internet-services/itunes/dev/stdeula/">https://www.apple.com/legal/internet-services/itunes/dev/stdeula/</a></p>
<p>Support: mark.gregory@abbeysoftware.com</p></main><footer>© 2026 Mark Gregory · <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a><p>Independent software. Not affiliated with or endorsed by the qBittorrent project.</p></footer></body></html>