Files
Tarnax/docs/VALIDATION.md
T
2026-11-05 10:42:10 +00:00

20 KiB
Raw Blame History

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

  1. Connect with the Web UI credentials, and separate proxy Basic credentials if needed. Confirm the server/API version.
  2. Compare the Library with qBittorrent Web UI. Verify Home excludes completed, paused, queued, checking and stalled entries.
  3. Add a lawful test magnet and a small .torrent file. Verify progress, speed, ETA and server save path.
  4. Pause/resume it; inspect files, skip a file, change a priority, and inspect peers/trackers. Test tracker editing only on a disposable torrent.
  5. Change a harmless preference, confirm read-back in the app and Web UI, then restore the original value.
  6. Test alternative limits and per-torrent limits. Queue-order controls require queueing enabled on the server.
  7. Remove the disposable torrent without files, then test permanent deletion only with expendable server data.
  8. Enable app protection; background and reopen the app. Test successful authentication, cancellation and passcode fallback.
  9. Rotate iPhone and iPad; check sidebar navigation, text sizes, dark/light modes and Files import.
  10. 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.

Status colours and detail controls — 5 November 2026

Shared torrent icons and bars now use yellow for downloads, purple for active seeding, red for stalled/error/missing files, pink for paused/stopped, orange for queued, and green for other completed transfers. Status-specific colours take priority over completion. Detail Resume/Pause/More share one button style with equal widths, 44-point minimum touch height, smaller subheadline labels and pressed feedback. Accessibility text sizes stack the controls vertically. Unsigned generic iOS Debug build succeeded; physical-device visual verification remains outstanding. Temporary build files and log are under ~/Developer/Scratch/Tarnax.

Saved status colour customisation — 5 November 2026

Settings → Status colours now provides native colour pickers for downloading, seeding, stalled, paused, queued, error and completed statuses, plus Restore default colours. RGB selections are encoded in device UserDefaults and restored on model initialization. Changes immediately update shared torrent row icons/bars, file progress bars and the Library legend. Stalled and error have independent colour choices. The Library legend also links directly to the editor. Unsigned generic iOS Debug build succeeded; diff whitespace validation passed. Picker interaction and relaunch on a physical device remain unverified. Temporary build files/log are under ~/Developer/Scratch/Tarnax.

Persistent local logs — 5 November 2026

Added Settings → Logs with newest-first timestamped activity/error entries and a confirmed Clear logs action that deletes the saved archive. Logs restore across launches, retain at most 1,000 entries and group adjacent identical events within a minute. Connection, preference loading, server actions and completion notification events are recorded. Reportable network failures include safe error codes; decoding failures are identified without saving payloads. Credentials, request fields, response bodies, server URLs and torrent names are excluded. Storage failures are shown in Logs. Privacy text updated.

Unsigned generic iOS Debug build succeeded. Standalone executable log checks passed for persistence/reload, duplicate grouping, capacity, privacy of network error userInfo, permanent clear/reload and failed-write feedback. The log checks are included in Tests/run.sh. Build/test temporary files are under ~/Developer/Scratch/Tarnax. Device UI verification remains outstanding.

Queue ordering and pull-to-refresh — 5 November 2026

Library defaults to persisted Queue order sorting, using qBittorrent priority positions and putting unnumbered entries last with deterministic name/hash ordering. Rows display queue positions. Queueing must be enabled server-side for numbered priorities. Missing priority remains compatible with older server responses. Home still filters only actively downloading states.

Pull-to-refresh now awaits any in-flight dashboard refresh instead of silently skipping it. Dashboard requests are session-owned and coalesced. Detail refresh updates the main torrent snapshot as well as properties/files/trackers/peers; Settings refresh updates dashboard and preferences, with pull-to-refresh also available in preference groups. Server already refreshes dashboard, transfer and build information. Unsigned generic iOS Debug build succeeded; 94 executable contracts, standalone log checks and three profile checks passed. Temporary files/logs remain under ~/Developer/Scratch/Tarnax.

Production readiness: this update has not undergone signed Release validation, physical-device/live-server acceptance or installation. Completion notifications still require foreground observation; immediate suspended/killed-app delivery requires server push and is not implemented.

Completed filter and selected colour correction — 5 November 2026

Completion now requires finite progress >= 1 instead of assuming UP states are completed. This keeps incomplete or rounded-near-100% entries out of Completed and avoids falsely filling their bars. Rows displayed in Library → Completed explicitly use the user's saved Completed colour for icon and progress; other Library filters/detail rows retain state-specific colours. Regression checks cover six upload-related states with incomplete progress, exact completion and near-completion. Unsigned iOS Debug build succeeded; 102 contract checks, log checks and three profile checks passed. Temporary files are under ~/Developer/Scratch/Tarnax. No device installation performed.

Configurable start/completion notifications — 5 November 2026

Settings → Notifications now independently enables Download started and Download complete, persisted in UserDefaults. Existing completion preference is retained; started notifications default off. System permission is requested when enabling a type; denied permission remains visible and a link opens iOS app settings. Permission changes temporarily disable the switches.

A dedicated transition tracker suppresses the first connection snapshot and duplicate polls, emits starts for newly active downloads or queued/paused downloads entering downloading/forcedDL, excludes metadata lookup and emits completion only after observed incomplete progress reaches completion. Session replacement/disconnect resets the tracker. Observation continues with notification types disabled so enabling a switch does not replay old transitions. Delivery checks session identity and logs fixed event descriptions without torrent names. Immediate suspended/killed-app alerts still require server push; transitions occurring entirely between polls cannot be reconstructed.

Unsigned iOS Debug build succeeded; 112 contract checks (including ten notification transition checks), log checks and three profile checks passed. Actual start-alert delivery and notification settings interaction on a device remain to be checked. All temporary files/logs are under ~/Developer/Scratch/Tarnax. No new installation performed.