14 KiB
Validation — 4 November 2026
Passed
- Xcode 27.2 (27B52), unsigned generic iOS device Debug build: BUILD SUCCEEDED.
- Final unsigned generic iOS device Release build, including app icon: BUILD SUCCEEDED.
- 37 executable transport/model contract checks: passed. Includes unsafe URL and redirect rejection, same-origin redirect acceptance, cookie jar isolation, proxy subpaths, Origin/Referer, Basic proxy auth, form encoding, HTTP/login failures, multipart file uploads, query construction, decoding and Home state filtering.
- Info.plist and project.pbxproj validated with plutil.
- Shared scheme, source references, asset catalog, icon and README present; ZIP integrity and required file checks passed.
Xcode's only build warning was “Metadata extraction skipped, no AppIntents.framework dependency found.” This app does not define App Intents.
Not verified here
- Live authentication or operations against torrent.absdev.net: no production credentials supplied or embedded.
- Runtime UI on iPhone/iPad, accessibility layout, Face ID, passcode fallback or a physical device.
- Signed installation, App Store validation or deployment. Select your development team and provisioning in Xcode.
- Every preference on every qBittorrent version. Preferences are discovered at runtime; unsupported/read-only or normalized values are reported using server response and read-back.
Simulator services were unavailable in the initial environment. Compilation used the real iOS device SDK; the executable contract harness ran on macOS with mocked network responses, not a simulator or live server.
Suggested device acceptance checks
- Connect with the Web UI credentials, and separate proxy Basic credentials if needed. Confirm the server/API version.
- Compare the Library with qBittorrent Web UI. Verify Home excludes completed, paused, queued, checking and stalled entries.
- Add a lawful test magnet and a small .torrent file. Verify progress, speed, ETA and server save path.
- Pause/resume it; inspect files, skip a file, change a priority, and inspect peers/trackers. Test tracker editing only on a disposable torrent.
- Change a harmless preference, confirm read-back in the app and Web UI, then restore the original value.
- Test alternative limits and per-torrent limits. Queue-order controls require queueing enabled on the server.
- Remove the disposable torrent without files, then test permanent deletion only with expendable server data.
- Enable app protection; background and reopen the app. Test successful authentication, cancellation and passcode fallback.
- Rotate iPhone and iPad; check sidebar navigation, text sizes, dark/light modes and Files import.
- Test offline refresh, incorrect proxy credentials, expired session and reconnect. Confirm no operation is duplicated by an automatic mutation retry.
Settings cancellation fix — 4 November 2026
- Moved preference request ownership from the SwiftUI view task to AppModel. Concurrent initial/reload callers await one session-owned task; cancelling a transient view does not cancel that request. Failed reloads retain the current preferences.
- Disconnect/reconnect cancels the preference task and clears its cache. Identity checks prevent retired sessions from publishing preferences, dashboard snapshots, or global network errors.
- Added cancellation checks around transport work, prevented overlapping dashboard refreshes, and commit dashboard responses together. Polling remains owned by RootView and does not invalidate the session or preference requests.
- Settings, Server, preference save, torrent actions, and detail loading ignore explicit CancellationError / URLError.cancelled signals. Active-session HTTP, decoding, timeout, and other network failures remain visible. No automatic login or mutation retries were added.
- Existing interface preserved.
- Unsigned generic iOS device Debug build: BUILD SUCCEEDED. Restricted compiler execution initially prevented SwiftUI macro expansion; rerunning with access to Xcode compiler services succeeded. Only App Intents metadata warning remained.
- 48 mocked macOS contract checks passed, including view cancellation, concurrent preference loads, failed reload retention, visible timeouts, explicit task cancellation, retired-session errors, and disconnect during loading.
- Intermittent navigation behavior on a physical device and live-server authentication were not exercised.
Changed files: Tarnax/Core.swift, Tarnax/Settings.swift, Tarnax/Details.swift, Tests/ContractTests.swift, VALIDATION.md.
Tarnax rename — 4 November 2026
Renamed the Home Screen display name, bundle name, in-app headings and alerts, unlock prompt, Xcode target/product and shared scheme to Tarnax. Updated README instructions. The initial branding pass retained the old project paths and installation identity; the complete rename below supersedes that choice.
Unsigned generic iOS device Debug build with scheme Tarnax: BUILD SUCCEEDED. Verified built app display name Tarnax and bundle identifier net.absdev.Tarnax. Info.plist and project.pbxproj pass plutil validation.
Launch branding and automatic sign-in — 4 November 2026
Added TarnaxIcon.png, TarnaxBrand.imageset, LaunchScreen.storyboard and a matching SwiftUI connecting view. Updated Info.plist and Xcode resources. Icon verified as opaque RGB, 1024×1024. Compiled storyboard rendered in a temporary iPhone simulator preview; icon also inspected on Home Screen.
Saved server credentials trigger one automatic sign-in per launch after unlocking. Fresh installs remain on the connection form; failures allow manual retry. Disconnect suppresses automatic reconnection for the launch and invalidates pending connection results. Credentials continue to use the existing Keychain identity.
54 executable contract checks passed, including new automatic sign-in eligibility, app lock, failed connection cleanup, no repeated retry, and explicit disconnect checks. Unsigned device and simulator Debug builds succeeded. Successful live-server authentication and physical-device launch timing were not tested.
Complete project rename — 4 November 2026
Renamed the enclosing folder to Tarnax, the project to Tarnax.xcodeproj and the source directory to Tarnax. Updated shared scheme container references, build paths, test runner, project labels, multipart boundary and documentation. Bundle identifier and Keychain service are now net.absdev.Tarnax. This supersedes the earlier decision to retain installation identifiers: iOS treats this as a new app and saved credentials must be entered once. Automatic sign-in then uses the new Keychain entry.
Complete rename verification: unsigned generic iOS Debug build succeeded; all 54 contract checks passed; built app identifier verified as net.absdev.Tarnax; no old app-name references remain in project files. Stale Xcode window state was backed up outside the project so Xcode can regenerate paths.
Build scripts and Apple UI guidance — 4 November 2026
Added scripts/build.sh, scripts/test.sh, scripts/release.sh and scripts/README.md. Verified unsigned Release build, script help/syntax, and all 54 contract checks. The release script creates timestamped archives/exports, retains logs, verifies signatures and embedded registered-device provisioning, and writes a SHA-256 checksum. Existing local assets successfully created a signed Release archive, but Ad Hoc export failed because no matching profile for net.absdev.Tarnax was installed. Account provisioning updates require explicit user approval after automatic review rejected that step.
UI changes: compact tab navigation with individual stacks, regular-width sidebar, scene-persisted selection, appearance-adaptive system launch screen, semantic colors and Dynamic Type in the connecting view, large-text transfer layouts, spoken metric labels, larger action targets, native cancellation placement and upload dismissal protection. The branded static launch design is superseded by Apple's recommended minimal launch treatment; branding remains in the icon and connecting view. No network or credential fixture was added to production code.
Final UI verification: production Release build succeeded; 54 contract checks passed. A separate sample-data simulator preview was inspected in light appearance and dark appearance at the largest accessibility text size. Full VoiceOver and physical-device testing remain outstanding. Ad Hoc IPA export remains blocked on the missing profile pending approval for account provisioning updates.
Approved IPA release: release-testing export succeeded with provisioning updates enabled. Tarnax 1.0 build 1; verified code signature, bundle identifier, profile application identifier, profile expiry 2027-09-03T11:17:13Z and four provisioned devices. Export contains IPA and SHA-256 checksum.
Face ID and deployment follow-up — 4 November 2026
Build 3 installed and launched on the paired iPhone; user confirmed Face ID unlocks successfully. Authentication now observes the scene lifecycle from RootView and accepts a successful evaluation during the system prompt's inactive phase, while rejecting results from a previous background lock cycle.
Build 4 hides the lock fallback during normal launch and Face ID evaluation, showing the dark Tarnax branded view instead. Cancelled, failed or incomplete authentication offers Unlock; retry immediately returns to branding. No protected content is shown before authentication. 71 executable contract checks and profile validation tests passed; signed Release built, installed and launched successfully on the iPhone.
Deploy script validates exact and wildcard Apple App IDs, checks device registration and expiry, and separates installation success from launch failure on a locked phone. Script-controlled temporary files and DerivedData now use ~/Developer/Scratch/Tarnax. Final build products remain under build/.
Live transfer history — 4 November 2026
Added bounded session history to dashboard refreshes, with 1-, 5- and 15-minute windows, separate upload/download series, chart selection and gaps after polling interruptions. History resets on connection replacement or disconnect; failed refreshes never fabricate samples. 83 contract checks passed, including timestamp boundary, retention, coalescing, capacity and refresh integration checks.
Build 5 crashed on the physical iPhone: the retrieved report and matching executable identified a null weak-linked Foundation Date >= call in chart filtering. Build 6 uses numeric timestamp comparisons instead; inspection confirmed no weak-linked Date >= or <= entry points remain. User confirmed Home and graph work on the iPhone after build 6 installation.
Build 7 adds blue/indigo/violet download strokes, teal dashed upload strokes, independent translucent gradient fills, endpoint/selection dots, a soft plot background and coordinated speed values. Signed Release build passed and binary compatibility inspection passed. Installed on the iPhone; automatic launch was blocked because the phone was locked. No new network or sampling behavior was introduced by the colour change.
Accumulated iOS fixes — 5 November 2026
- Retained session-owned, deduplicated Settings loading and root-owned dashboard polling. Tightened cancellation reporting: retired sessions and explicit Swift task cancellation stay silent; URLError.cancelled is silent only when its task is cancelled. Unexpected cancellation, timeout, HTTP and decoding failures remain visible.
- Timestamped upload/download history now uses an atomic Codable archive in Application Support, scoped to the configured server and username. Restored during model initialization and connection; rolling 24-hour pruning, bounded one-second sampling, and segment breaks after missing measurements. Failed refreshes never fabricate data. Forget credentials removes the local archive. Persistence failures are visible on Home/Library. Default chart window is 24 hours.
- Completed/seeding torrents use green progress in the shared Library/detail row; completed files also use green bars. Home retains its original downloading-only state filter.
- Detail action controls use ViewThatFits to wrap vertically on narrow layouts or large text. Existing advanced actions remain in More. Native bordered buttons give pressed feedback; per-torrent pending state prevents duplicate actions and shows progress, success and failure. Inapplicable pause/resume and completed download-priority actions are disabled. Torrent deletion and tracker removal require confirmation. Mutation success is returned directly instead of inferred from an unrelated global alert.
- Explicit unit metadata formats known server/detail statistics and preference summaries as readable durations, sizes and speeds. Editors preserve raw values and state the input units. Unknown fields remain raw rather than guessing from their names. Seeding limits use minutes; slow-torrent inactivity uses seconds; refresh interval uses milliseconds; cache uses MiB. Checked against qBittorrent API documentation and AppController source.
- Added opt-in local completion notifications in Settings, requesting system permission and presenting foreground banners/sound. Only an observed incomplete-to-complete transition alerts; initial existing completions do not flood notifications. No background polling entitlement or server push was added: suspended apps detect completion on their next foreground refresh; killed-app completions are not guaranteed notifications. Real device notification delivery remains to be verified.
- Credentials remain in the existing Keychain service; HTTPS transport, private cookies, server configuration and existing qBittorrent endpoints are preserved.
- Temporary build/test files and logs are under ~/Developer/Scratch/Tarnax per user instruction. Unrelated website changes were left untouched.
Device acceptance still required: narrow iPhone/iPad widths and largest Dynamic Type, live server actions, Settings navigation under poor connectivity, background/relaunch graph restoration, notification permission denial and successful completion delivery. No signed deployment performed for this update.
Final verification: unsigned generic iOS device Debug build BUILD SUCCEEDED; 91 executable model/transport/persistence/formatting contract checks passed, including Settings view cancellation and real-error reporting; three provisioning-profile tests passed; project/Info.plist validation and diff whitespace checks passed. Logs: ~/Developer/Scratch/Tarnax/build-verified.log and tests-verified.log. Physical-device and live-server verification remain outstanding.