Sync Home with pull then push and prepare 1.0.1 build 8 (#124)
Dependency security audit / rustsec (push) Successful in 20s
Tagged release / prepare-release (push) Successful in 4s
Tagged release / build-unix (push) Successful in 1h15m17s
Tagged release / build-windows (push) Successful in 19m26s
Tagged release / publish-release (push) Successful in 3s
Dependency security audit / rustsec (push) Successful in 20s
Tagged release / prepare-release (push) Successful in 4s
Tagged release / build-unix (push) Successful in 1h15m17s
Tagged release / build-windows (push) Successful in 19m26s
Tagged release / publish-release (push) Successful in 3s
This commit is contained in:
1 parent
3c3574b449
commit
aec3f237a9
12 files changed
+1174
-50
No files matched your search
@@ -15,11 +15,11 @@ copyright = "2026 rfc1437"
|
||||
review_notes = "IronStorage works entirely on-device without an account or remote service. On first launch, generate a local GPG key and choose a passphrase. You can then create folders without unlocking, and create encrypted password or TOTP entries after entering that passphrase. Git history is initialized locally; HTTPS synchronization is optional and is not needed for review. Entries appear on Apple Watch only after selecting them for Watch sharing on iPhone."
|
||||
|
||||
[release]
|
||||
version = "1.0"
|
||||
build = "7"
|
||||
version = "1.0.1"
|
||||
build = "8"
|
||||
minimum_ios = "17.0"
|
||||
minimum_watchos = "26.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."
|
||||
notes = "Pull down on Home to pull remote changes and then push local commits. Pull failures stop synchronization and are shown immediately. Includes OTP QR import improvements and the Apple Watch companion."
|
||||
|
||||
[[screenshots]]
|
||||
file = "apple/AppStore/screenshots/iphone-6.5/home.png"
|
||||
|
||||
@@ -1254,6 +1254,8 @@ public protocol MobileHomeOperationProtocol: AnyObject, Sendable {
|
||||
|
||||
func refreshIfStale() throws -> MobileHomePage
|
||||
|
||||
func sync() throws -> MobileHomePage
|
||||
|
||||
}
|
||||
open class MobileHomeOperation: MobileHomeOperationProtocol, @unchecked Sendable {
|
||||
fileprivate let handle: UInt64
|
||||
@@ -1380,6 +1382,15 @@ open func refreshIfStale()throws -> MobileHomePage {
|
||||
})
|
||||
}
|
||||
|
||||
open func sync()throws -> MobileHomePage {
|
||||
return try FfiConverterTypeMobileHomePage_lift(try rustCallWithError(FfiConverterTypeMobileHomeFfiError_lift) {
|
||||
uniffiCallStatus in
|
||||
uniffi_ironstorage_apple_fn_method_mobilehomeoperation_sync(
|
||||
self.uniffiCloneHandle(),uniffiCallStatus
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -8120,6 +8131,9 @@ private let initializationResult: InitializationResult = {
|
||||
if (uniffi_ironstorage_apple_checksum_method_mobilehomeoperation_refresh_if_stale() != 27818) {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if (uniffi_ironstorage_apple_checksum_method_mobilehomeoperation_sync() != 48214) {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
if (uniffi_ironstorage_apple_checksum_method_mobilekeytransfer_export() != 50467) {
|
||||
return InitializationResult.apiChecksumMismatch
|
||||
}
|
||||
|
||||
@@ -518,6 +518,11 @@ RustBuffer uniffi_ironstorage_apple_fn_method_mobilehomeoperation_push(uint64_t
|
||||
RustBuffer uniffi_ironstorage_apple_fn_method_mobilehomeoperation_refresh_if_stale(uint64_t ptr, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_FN_METHOD_MOBILEHOMEOPERATION_SYNC
|
||||
#define UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_FN_METHOD_MOBILEHOMEOPERATION_SYNC
|
||||
RustBuffer uniffi_ironstorage_apple_fn_method_mobilehomeoperation_sync(uint64_t ptr, RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_FN_CLONE_MOBILEKEYTRANSFER
|
||||
#define UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_FN_CLONE_MOBILEKEYTRANSFER
|
||||
uint64_t uniffi_ironstorage_apple_fn_clone_mobilekeytransfer(uint64_t handle, RustCallStatus *_Nonnull out_status
|
||||
@@ -1363,6 +1368,12 @@ uint16_t uniffi_ironstorage_apple_checksum_method_mobilehomeoperation_push(void
|
||||
#define UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_CHECKSUM_METHOD_MOBILEHOMEOPERATION_REFRESH_IF_STALE
|
||||
uint16_t uniffi_ironstorage_apple_checksum_method_mobilehomeoperation_refresh_if_stale(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_CHECKSUM_METHOD_MOBILEHOMEOPERATION_SYNC
|
||||
#define UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_CHECKSUM_METHOD_MOBILEHOMEOPERATION_SYNC
|
||||
uint16_t uniffi_ironstorage_apple_checksum_method_mobilehomeoperation_sync(void
|
||||
|
||||
);
|
||||
#endif
|
||||
#ifndef UNIFFI_FFIDEF_UNIFFI_IRONSTORAGE_APPLE_CHECKSUM_METHOD_MOBILEKEYTRANSFER_EXPORT
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -388,9 +388,11 @@ private final class ShellViewController: UITableViewController, MobileTabRoot {
|
||||
case fetch
|
||||
case pull
|
||||
case push
|
||||
case sync
|
||||
|
||||
var changesLocalStore: Bool {
|
||||
if case .pull = self { return true }
|
||||
if case .sync = self { return true }
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -577,7 +579,7 @@ private final class ShellViewController: UITableViewController, MobileTabRoot {
|
||||
refreshControl?.endRefreshing()
|
||||
return
|
||||
}
|
||||
runHome(.pull)
|
||||
runHome(.sync)
|
||||
} else {
|
||||
reloadShell()
|
||||
}
|
||||
@@ -750,7 +752,7 @@ private final class ShellViewController: UITableViewController, MobileTabRoot {
|
||||
let refreshed = page.refreshedAt.map(formattedDate)
|
||||
switch page.freshness {
|
||||
case .neverRefreshed:
|
||||
return "Not refreshed. Pull down to update the local clone or tap Refresh Status."
|
||||
return "Not refreshed. Pull down to pull, then push your changes, or tap Refresh Status."
|
||||
case .cached:
|
||||
return "Cached · Last refreshed \(refreshed ?? "at an unknown time"). This is not live status."
|
||||
case .current:
|
||||
@@ -822,6 +824,7 @@ private final class ShellViewController: UITableViewController, MobileTabRoot {
|
||||
case .fetch: try operation.fetch()
|
||||
case .pull: try operation.pull()
|
||||
case .push: try operation.push()
|
||||
case .sync: try operation.sync()
|
||||
}
|
||||
return Result<MobileHomePage, HomeFailure>.success(page)
|
||||
} catch let error as MobileHomeFfiError {
|
||||
@@ -865,11 +868,16 @@ private final class ShellViewController: UITableViewController, MobileTabRoot {
|
||||
UIAccessibility.post(notification: .announcement, argument: notice.title)
|
||||
}
|
||||
case let .failure(failure):
|
||||
if request == .sync {
|
||||
// Pull may have updated entries before a later push failed.
|
||||
NotificationCenter.default.post(name: .ironStorageLocalStoreDidChange, object: nil)
|
||||
NotificationCenter.default.post(name: .ironStorageWatchSnapshotDidChange, object: nil)
|
||||
}
|
||||
tableView.reloadData()
|
||||
if homePage == nil {
|
||||
showHomeFailure(failure)
|
||||
presentHomeFailure(failure, retry: request ?? .fetch)
|
||||
} else if failure.kind == .interrupted {
|
||||
} else if failure.kind == .interrupted, request != .sync {
|
||||
UIAccessibility.post(notification: .announcement, argument: failure.title)
|
||||
} else {
|
||||
presentHomeFailure(failure, retry: request ?? .fetch)
|
||||
|
||||
+7
-1
@@ -9,7 +9,7 @@ actually exercised.
|
||||
|
||||
| Area | Implemented boundary | Automated evidence | Manual release evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| Home tab, local history, and optional remote activity | UIKit renders Rust `MobileHomePage` and typed Commit/Fetch/Pull/Push actions | `mobile_home` unit tests, `git_embedded`, and `crates/apple` bridge tests | Verify a clean local store first, then attach a disposable HTTPS remote and exercise refresh and all four actions, including expired application-token recovery |
|
||||
| Home tab, local history, and optional remote activity | UIKit renders Rust `MobileHomePage`; pulling down calls Rust sync (pull, then push only on success). Explicit Commit/Fetch/Pull/Push actions remain available. | `mobile_home` unit tests, `git_embedded` move/back and failed-pull regressions, and `crates/apple` bridge tests | Verify refresh and all four actions, including expired application-token recovery. Pull failures must show an error and prevent push. |
|
||||
| Passwords tab, navigation, view, and edit | Rust supplies typed paths, fields, drafts, revisions, and mutations; UIKit presents them | `mobile_passwords`, `entry_documents`, `mobile_mutation`, and `mobile_authentication` tests | Open nested entries, edit/save/cancel, and confirm stale-edit recovery |
|
||||
| Swipe move/copy/delete | Rust plans destinations, collisions, dirty-editor handling, and commits; UIKit also exposes accessibility actions | `plans_destinations_collisions_hidden_paths_and_stale_revisions` and authentication serialization tests | Exercise swipe and VoiceOver alternatives; confirm destructive prompts |
|
||||
| TOTP tab and sharing | Rust discovers, caches, parses, selects, and generates OTP data | `mobile_totp`, `otp`, and `mobile_watch` integration tests | Discover entries, read a code, change Watch selection, and verify countdown |
|
||||
@@ -88,6 +88,12 @@ the tester is ready to enter the passphrase again.
|
||||
|
||||
## Manual evidence still required
|
||||
|
||||
Issue #124 / version 1.0.1 build 8: iPhone and Watch simulator builds passed;
|
||||
the existing iPhone simulator installation was updated in place and Home opened.
|
||||
Automated Git tests cover move-and-move-back commits, network/authentication
|
||||
failures, and merge conflicts without a subsequent push. Live account sync is
|
||||
deferred to the user's TestFlight validation; no physical iPhone was updated.
|
||||
|
||||
Issue #120 was exercised on 2026-09-12 using the existing iPhone 17 Pro / iOS
|
||||
26.5 simulator (`FB5C6929-C10D-40C8-9A94-5CC592037FDB`) and its simulated store.
|
||||
TOTP Add imported a synthetic QR into `otp/Simulator Panel OTP`; the normal
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ settings:
|
||||
SWIFT_VERSION: "5.0"
|
||||
CODE_SIGN_STYLE: Automatic
|
||||
DEVELOPMENT_TEAM: MU22FMRGK8
|
||||
MARKETING_VERSION: "1.0"
|
||||
CURRENT_PROJECT_VERSION: "7"
|
||||
MARKETING_VERSION: "1.0.1"
|
||||
CURRENT_PROJECT_VERSION: "8"
|
||||
targets:
|
||||
IronStorage:
|
||||
type: application
|
||||
|
||||
Reference in new issue
Block a user