From 856b55f64f020dd26ef514a9a083754dcb065741 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 11:14:35 +0000 Subject: [PATCH 1/9] chore(deps): bump libc from 0.2.189 to 0.2.190 in /src-tauri Bumps [libc](https://github.com/rust-lang/libc) from 0.2.189 to 0.2.190. - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.190/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.189...0.2.190) --- updated-dependencies: - dependency-name: libc dependency-version: 0.2.190 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9ec672c0..066dc9d9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3145,9 +3145,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "libdbus-sys" From 63c072b127ea92956c1fa2f6452f1cad93c21dca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 11:15:05 +0000 Subject: [PATCH 2/9] chore(deps): bump objc2 from 0.6.4 to 0.6.5 in /src-tauri Bumps [objc2](https://github.com/madsmtm/objc2) from 0.6.4 to 0.6.5. - [Commits](https://github.com/madsmtm/objc2/compare/objc2-0.6.4...objc2-0.6.5) --- updated-dependencies: - dependency-name: objc2 dependency-version: 0.6.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 066dc9d9..f45ee675 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3473,9 +3473,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8" dependencies = [ "objc2-encode", "objc2-exception-helper", From 96c35b2d64ead674a2ab66176306d597362ea967 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 11:15:11 +0000 Subject: [PATCH 3/9] chore(deps): bump tokio from 1.53.1 to 1.53.2 in /src-tauri Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.53.1 to 1.53.2. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.53.1...tokio-1.53.2) --- updated-dependencies: - dependency-name: tokio dependency-version: 1.53.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f45ee675..02f8f63f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6324,9 +6324,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.53.1" +version = "1.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" dependencies = [ "bytes", "libc", From 0dd0f94cb41f07915a40b42cbfd74c568b193df4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 11:14:49 +0000 Subject: [PATCH 4/9] chore(deps): bump zeroize from 1.9.0 to 1.9.1 in /src-tauri Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.9.0 to 1.9.1. - [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.9.0...zeroize-v1.9.1) --- updated-dependencies: - dependency-name: zeroize dependency-version: 1.9.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 02f8f63f..2a95e5d8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -8023,9 +8023,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" dependencies = [ "serde", "zeroize_derive", From 2d97eebc984c5e1e3e01e25cb3bff76eb663603d Mon Sep 17 00:00:00 2001 From: Alex Chaplinsky Date: Sun, 11 Oct 2026 01:11:13 +0700 Subject: [PATCH 5/9] ci(deps): catch stale UniFFI bindings, group safe Dependabot bumps - ios job regenerates the AutoFill bindings and fails on any diff; a stale copy builds fine and aborts the extension at its first Rust call (114c3458, #563). - bindgen.sh passes --no-format so its output doesn't depend on the local Xcode's swift-format. - dependabot.yml: one grouped PR per ecosystem for safe bumps (cargo: patch only, since 0.x minors break), a 7-day cooldown, and coverage for extension/. --- .github/dependabot.yml | 61 ++++++++++++++++++++++++++-- .github/workflows/ci.yml | 11 +++++ src-tauri/crates/autofill/bindgen.sh | 6 ++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ca992229..11d4118a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,16 @@ -# Dependabot keeps dependencies patched across all three ecosystems the app -# ships from: the JS frontend (npm, repo root), the Rust backend (cargo, -# src-tauri/), and the CI/release workflows themselves (github-actions). +# Dependabot keeps dependencies patched across the ecosystems the app ships +# from: the JS frontend (npm, repo root), the Rust backend (cargo, +# src-tauri/), the browser extension (npm, extension/), and the CI/release +# workflows themselves (github-actions). # All PRs target main (the default branch); release branches are cut from it. +# +# Each PR is tested against main alone, never alongside the others, so merging +# several in a row can still break main. Safe bumps are therefore grouped into +# one PR per ecosystem, and anything that can break the API arrives on its own +# PR, to be landed together with the code it needs. +# +# A dependency joins the first group it matches, so the release-train groups +# come before the catch-all ones. version: 2 updates: # JS/TS frontend — package.json / bun.lock at the repo root. @@ -9,6 +18,9 @@ updates: directory: / schedule: interval: weekly + # A release has a week to be yanked before it is proposed. + cooldown: + default-days: 7 target-branch: main open-pull-requests-limit: 10 labels: @@ -24,12 +36,20 @@ updates: tauri-js: patterns: - '@tauri-apps/*' + npm-minor-patch: + patterns: + - '*' + update-types: + - minor + - patch # Rust backend — src-tauri/Cargo.toml + Cargo.lock. - package-ecosystem: cargo directory: /src-tauri schedule: interval: weekly + cooldown: + default-days: 7 target-branch: main open-pull-requests-limit: 10 labels: @@ -45,6 +65,14 @@ updates: passkey-rs: patterns: - 'passkey-*' + # Patch only: Dependabot calls 0.29 -> 0.32 a minor update, but below + # 1.0 Cargo treats it as breaking (uniffi, passkey-rs and + # windows-registry all broke this way), so minors arrive one per PR. + cargo-patch: + patterns: + - '*' + update-types: + - patch ignore: # passkey-rs requires p256 ^0.13. 0.14 would link a second copy and # break the COSE key bridge. Lift once passkey-rs moves to p256 0.14. @@ -60,13 +88,40 @@ updates: - dependency-name: rand versions: ['>=0.9'] + # Browser extension — extension/package.json + package-lock.json. A fork of + # KeePassXC-Browser with dev-only tooling, so one monthly PR is enough. + - package-ecosystem: npm + directory: /extension + schedule: + interval: monthly + cooldown: + default-days: 7 + target-branch: main + open-pull-requests-limit: 5 + labels: + - dependencies + - javascript + groups: + extension: + patterns: + - '*' + # GitHub Actions used by ci.yml / release.yml / codeql.yml. - package-ecosystem: github-actions directory: / schedule: interval: weekly + cooldown: + default-days: 7 target-branch: main open-pull-requests-limit: 10 labels: - dependencies - ci + groups: + actions-minor-patch: + patterns: + - '*' + update-types: + - minor + - patch diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aac4840b..a1c77ec3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -220,6 +220,17 @@ jobs: working-directory: src-tauri run: cargo clippy --target aarch64-apple-ios-sim --all-targets -- -D warnings + # The AutoFill extension's Swift bindings are committed, and UniFFI checks + # them against the library on load: a stale copy builds fine and then + # aborts the extension at its first Rust call. A doc-comment edit + # (114c3458) and a uniffi bump (#563) each shipped one. + - name: AutoFill UniFFI bindings are current + run: | + set -euo pipefail + sh src-tauri/crates/autofill/bindgen.sh + git diff --exit-code -- src-tauri/gen/apple/Sources/autofill/generated \ + || { echo '::error::Stale UniFFI bindings: run src-tauri/crates/autofill/bindgen.sh and commit what it writes'; exit 1; } + # Malformed XML in any of these only surfaces at build or upload time # otherwise, and a dropped privacy manifest is not an error at all — App # Store Connect just rejects the submission by email days later. diff --git a/src-tauri/crates/autofill/bindgen.sh b/src-tauri/crates/autofill/bindgen.sh index 9eff2fac..5a89922d 100755 --- a/src-tauri/crates/autofill/bindgen.sh +++ b/src-tauri/crates/autofill/bindgen.sh @@ -14,6 +14,10 @@ # `uniffi-bindgen` binary in this crate (the version the runtime is). Built for # the host — the bindings are the same for every target. Honours # CARGO_TARGET_DIR like any cargo command. +# +# CI re-runs this and fails on any difference (the `ios` job in ci.yml), so the +# output must not depend on the machine: `--no-format` keeps whatever +# swift-format the local Xcode ships out of it. set -eu cd "$(dirname "$0")/../.." @@ -23,4 +27,4 @@ out=gen/apple/Sources/autofill/generated cargo build -p rowel-autofill cargo run -q -p rowel-autofill --features bindgen --bin uniffi-bindgen -- \ generate --library "$target_dir/debug/librowel_autofill.a" \ - --language swift --out-dir "$out" + --language swift --no-format --out-dir "$out" From 8b9d2654690ea8b17e121f2740292e0898343cd1 Mon Sep 17 00:00:00 2001 From: Alex Chaplinsky Date: Sun, 11 Oct 2026 01:12:52 +0700 Subject: [PATCH 6/9] fix(ios): regenerate the AutoFill UniFFI bindings for uniffi 0.32 #563 bumped uniffi from 0.29 to 0.32 without re-running bindgen.sh. The library now reports contract version 30 and new API checksums, while the committed Swift still expected 29, so the extension hit fatalError("UniFFI contract version mismatch") on its first Rust call. Regenerated with bindgen.sh. The public Swift API is unchanged; only the generated internals move (object pointers become handles, Equatable and Hashable are synthesized). --- .../autofill/generated/rowel_autofill.swift | 507 +++++++----------- .../autofill/generated/rowel_autofillFFI.h | 192 +++---- 2 files changed, 275 insertions(+), 424 deletions(-) diff --git a/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofill.swift b/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofill.swift index 20fb051e..dabc3f04 100644 --- a/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofill.swift +++ b/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofill.swift @@ -39,6 +39,52 @@ fileprivate extension ForeignBytes { init(bufferPointer: UnsafeBufferPointer) { self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress) } + + init(rawBufferPointer: UnsafeRawBufferPointer) { + self.init( + len: Int32(rawBufferPointer.count), + data: rawBufferPointer.baseAddress?.assumingMemoryBound(to: UInt8.self) + ) + } +} + +// Converter for `&[u8]` / `[ByRef] bytes` arguments. +// +// Conforms to `FfiConverter` so the compiler enforces the full converter +// method set. Only the scope-bound `lower(_:_body:)` overload is sound — +// zero-copy byte buffers only flow foreign -> Rust, and only in argument +// position. The four protocol-witness methods (`lift`, `lower`, `read`, +// `write`) `fatalError` at runtime if anyone reaches them. +// +// The scope-bound `lower` takes a closure because the `ForeignBytes` +// pointer is only guaranteed valid for the duration of +// `Data.withUnsafeBytes`. Callers must run the full FFI call inside +// the closure body. +fileprivate enum FfiConverterByRefBytes: FfiConverter { + typealias SwiftType = Data + typealias FfiType = ForeignBytes + + static func lower(_ value: Data, _ body: (ForeignBytes) throws -> R) rethrows -> R { + return try value.withUnsafeBytes { rawBuf in + try body(ForeignBytes(rawBufferPointer: rawBuf)) + } + } + + static func lower(_ value: Data) -> ForeignBytes { + fatalError("ByRef bytes cannot use the plain lower: returning ForeignBytes escapes the Data.withUnsafeBytes scope. Use the scope-bound lower(_:_body:) overload instead.") + } + + static func lift(_ value: ForeignBytes) throws -> Data { + fatalError("ByRef bytes cannot be lifted: zero-copy &[u8] only flows foreign->Rust") + } + + static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Data { + fatalError("ByRef bytes cannot be read from a buffer: zero-copy &[u8] is only supported in argument position, not nested in records/options/etc.") + } + + static func write(_ value: Data, into buf: inout [UInt8]) { + fatalError("ByRef bytes cannot be written to a buffer: zero-copy &[u8] is only supported in argument position, not nested in records/options/etc.") + } } // For every type used in the interface, we provide helper methods for conveniently @@ -352,21 +398,31 @@ private func uniffiTraitInterfaceCallWithError( callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) } } +// Initial value and increment amount for handles. +// These ensure that SWIFT handles always have the lowest bit set +fileprivate let UNIFFI_HANDLEMAP_INITIAL: UInt64 = 1 +fileprivate let UNIFFI_HANDLEMAP_DELTA: UInt64 = 2 + fileprivate final class UniffiHandleMap: @unchecked Sendable { // All mutation happens with this lock held, which is why we implement @unchecked Sendable. private let lock = NSLock() private var map: [UInt64: T] = [:] - private var currentHandle: UInt64 = 1 + private var currentHandle: UInt64 = UNIFFI_HANDLEMAP_INITIAL func insert(obj: T) -> UInt64 { lock.withLock { - let handle = currentHandle - currentHandle += 1 - map[handle] = obj - return handle + return doInsert(obj) } } + // Low-level insert function, this assumes `lock` is held. + private func doInsert(_ obj: T) -> UInt64 { + let handle = currentHandle + currentHandle += UNIFFI_HANDLEMAP_DELTA + map[handle] = obj + return handle + } + func get(handle: UInt64) throws -> T { try lock.withLock { guard let obj = map[handle] else { @@ -376,6 +432,15 @@ fileprivate final class UniffiHandleMap: @unchecked Sendable { } } + func clone(handle: UInt64) throws -> UInt64 { + try lock.withLock { + guard let obj = map[handle] else { + throw UniffiInternalError.unexpectedStaleHandle + } + return doInsert(obj) + } + } + @discardableResult func remove(handle: UInt64) throws -> T { try lock.withLock { @@ -428,7 +493,11 @@ fileprivate struct FfiConverterString: FfiConverter { return String() } let bytes = UnsafeBufferPointer(start: value.data!, count: Int(value.len)) - return String(bytes: bytes, encoding: String.Encoding.utf8)! + // Use Swift's native UTF-8 decoder; `String(bytes:encoding:.utf8)` goes + // through Foundation's NSString and silently strips a leading U+FEFF BOM. + // Invalid UTF-8 substitutes U+FFFD instead of trapping (unreachable + // given Rust's `String` invariant). + return String(decoding: bytes, as: UTF8.self) } public static func lower(_ value: String) -> RustBuffer { @@ -444,7 +513,8 @@ fileprivate struct FfiConverterString: FfiConverter { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String { let len: Int32 = try readInt(&buf) - return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)! + // See `lift` above for why we avoid Foundation's NSString-backed decoder here. + return String(decoding: try readBytes(&buf, count: Int(len)), as: UTF8.self) } public static func write(_ value: String, into buf: inout [UInt8]) { @@ -533,13 +603,13 @@ public protocol VaultProtocol: AnyObject, Sendable { * An open vault. Lives as long as the extension's sheet. */ open class Vault: VaultProtocol, @unchecked Sendable { - fileprivate let pointer: UnsafeMutableRawPointer! + fileprivate let handle: UInt64 - /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. + /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly. #if swift(>=5.8) @_documentation(visibility: private) #endif - public struct NoPointer { + public struct NoHandle { public init() {} } @@ -549,36 +619,37 @@ open class Vault: VaultProtocol, @unchecked Sendable { #if swift(>=5.8) @_documentation(visibility: private) #endif - required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { - self.pointer = pointer + required public init(unsafeFromHandle handle: UInt64) { + self.handle = handle } // This constructor can be used to instantiate a fake object. - // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // - Parameter noHandle: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. // // - Warning: - // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing handle the FFI lower functions will crash. #if swift(>=5.8) @_documentation(visibility: private) #endif - public init(noPointer: NoPointer) { - self.pointer = nil + public init(noHandle: NoHandle) { + self.handle = 0 } #if swift(>=5.8) @_documentation(visibility: private) #endif - public func uniffiClonePointer() -> UnsafeMutableRawPointer { - return try! rustCall { uniffi_rowel_autofill_fn_clone_vault(self.pointer, $0) } + public func uniffiCloneHandle() -> UInt64 { + return try! rustCall { uniffi_rowel_autofill_fn_clone_vault(self.handle, $0) } } // No primary constructor declared for this class. deinit { - guard let pointer = pointer else { + if handle == 0 { + // Mock objects have handle=0 don't try to free them return } - try! rustCall { uniffi_rowel_autofill_fn_free_vault(pointer, $0) } + try! rustCall { uniffi_rowel_autofill_fn_free_vault(handle, $0) } } @@ -592,8 +663,10 @@ open class Vault: VaultProtocol, @unchecked Sendable { */ open func assertPasskey(request: PasskeyAssertion)throws -> AssertedPasskey { return try FfiConverterTypeAssertedPasskey_lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { - uniffi_rowel_autofill_fn_method_vault_assert_passkey(self.uniffiClonePointer(), - FfiConverterTypePasskeyAssertion_lower(request),$0 + uniffiCallStatus in + uniffi_rowel_autofill_fn_method_vault_assert_passkey( + self.uniffiCloneHandle(), + FfiConverterTypePasskeyAssertion_lower(request),uniffiCallStatus ) }) } @@ -610,8 +683,10 @@ open func assertPasskey(request: PasskeyAssertion)throws -> AssertedPasskey { */ open func credentialsFor(serviceIdentifiers: [String])throws -> [Credential] { return try FfiConverterSequenceTypeCredential.lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { - uniffi_rowel_autofill_fn_method_vault_credentials_for(self.uniffiClonePointer(), - FfiConverterSequenceString.lower(serviceIdentifiers),$0 + uniffiCallStatus in + uniffi_rowel_autofill_fn_method_vault_credentials_for( + self.uniffiCloneHandle(), + FfiConverterSequenceString.lower(serviceIdentifiers),uniffiCallStatus ) }) } @@ -623,9 +698,11 @@ open func credentialsFor(serviceIdentifiers: [String])throws -> [Credential] { */ open func passkeysFor(rpId: String, allowedCredentialIds: [Data])throws -> [PasskeyAccount] { return try FfiConverterSequenceTypePasskeyAccount.lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { - uniffi_rowel_autofill_fn_method_vault_passkeys_for(self.uniffiClonePointer(), + uniffiCallStatus in + uniffi_rowel_autofill_fn_method_vault_passkeys_for( + self.uniffiCloneHandle(), FfiConverterString.lower(rpId), - FfiConverterSequenceData.lower(allowedCredentialIds),$0 + FfiConverterSequenceData.lower(allowedCredentialIds),uniffiCallStatus ) }) } @@ -641,9 +718,11 @@ open func passkeysFor(rpId: String, allowedCredentialIds: [Data])throws -> [Pas */ open func password(record: String, serviceIdentifiers: [String])throws -> Password { return try FfiConverterTypePassword_lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { - uniffi_rowel_autofill_fn_method_vault_password(self.uniffiClonePointer(), + uniffiCallStatus in + uniffi_rowel_autofill_fn_method_vault_password( + self.uniffiCloneHandle(), FfiConverterString.lower(record), - FfiConverterSequenceString.lower(serviceIdentifiers),$0 + FfiConverterSequenceString.lower(serviceIdentifiers),uniffiCallStatus ) }) } @@ -658,13 +737,16 @@ open func password(record: String, serviceIdentifiers: [String])throws -> Passw */ open func registerPasskey(request: PasskeyRegistration)throws -> RegisteredPasskey { return try FfiConverterTypeRegisteredPasskey_lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { - uniffi_rowel_autofill_fn_method_vault_register_passkey(self.uniffiClonePointer(), - FfiConverterTypePasskeyRegistration_lower(request),$0 + uniffiCallStatus in + uniffi_rowel_autofill_fn_method_vault_register_passkey( + self.uniffiCloneHandle(), + FfiConverterTypePasskeyRegistration_lower(request),uniffiCallStatus ) }) } + } @@ -672,33 +754,24 @@ open func registerPasskey(request: PasskeyRegistration)throws -> RegisteredPass @_documentation(visibility: private) #endif public struct FfiConverterTypeVault: FfiConverter { - - typealias FfiType = UnsafeMutableRawPointer + typealias FfiType = UInt64 typealias SwiftType = Vault - public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Vault { - return Vault(unsafeFromRawPointer: pointer) + public static func lift(_ handle: UInt64) throws -> Vault { + return Vault(unsafeFromHandle: handle) } - public static func lower(_ value: Vault) -> UnsafeMutableRawPointer { - return value.uniffiClonePointer() + public static func lower(_ value: Vault) -> UInt64 { + return value.uniffiCloneHandle() } public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Vault { - let v: UInt64 = try readInt(&buf) - // The Rust code won't compile if a pointer won't fit in a UInt64. - // We have to go via `UInt` because that's the thing that's the size of a pointer. - let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if (ptr == nil) { - throw UniffiInternalError.unexpectedNullPointer - } - return try lift(ptr!) + let handle: UInt64 = try readInt(&buf) + return try lift(handle) } public static func write(_ value: Vault, into buf: inout [UInt8]) { - // This fiddling is because `Int` is the thing that's the same size as a pointer. - // The Rust code won't compile if a pointer won't fit in a `UInt64`. - writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + writeInt(&buf, lower(value)) } } @@ -706,14 +779,14 @@ public struct FfiConverterTypeVault: FfiConverter { #if swift(>=5.8) @_documentation(visibility: private) #endif -public func FfiConverterTypeVault_lift(_ pointer: UnsafeMutableRawPointer) throws -> Vault { - return try FfiConverterTypeVault.lift(pointer) +public func FfiConverterTypeVault_lift(_ handle: UInt64) throws -> Vault { + return try FfiConverterTypeVault.lift(handle) } #if swift(>=5.8) @_documentation(visibility: private) #endif -public func FfiConverterTypeVault_lower(_ value: Vault) -> UnsafeMutableRawPointer { +public func FfiConverterTypeVault_lower(_ value: Vault) -> UInt64 { return FfiConverterTypeVault.lower(value) } @@ -723,7 +796,7 @@ public func FfiConverterTypeVault_lower(_ value: Vault) -> UnsafeMutableRawPoint /** * What `ASPasskeyAssertionCredential` carries back besides what iOS sent. */ -public struct AssertedPasskey { +public struct AssertedPasskey: Equatable, Hashable { public var credentialId: Data public var userHandle: Data public var authenticatorData: Data @@ -743,40 +816,16 @@ public struct AssertedPasskey { self.authenticatorData = authenticatorData self.signature = signature } + + + + } #if compiler(>=6) extension AssertedPasskey: Sendable {} #endif - -extension AssertedPasskey: Equatable, Hashable { - public static func ==(lhs: AssertedPasskey, rhs: AssertedPasskey) -> Bool { - if lhs.credentialId != rhs.credentialId { - return false - } - if lhs.userHandle != rhs.userHandle { - return false - } - if lhs.authenticatorData != rhs.authenticatorData { - return false - } - if lhs.signature != rhs.signature { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(credentialId) - hasher.combine(userHandle) - hasher.combine(authenticatorData) - hasher.combine(signature) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -820,7 +869,7 @@ public func FfiConverterTypeAssertedPasskey_lower(_ value: AssertedPasskey) -> R * name it signs in with and its site. `record` is the credential identity's * `"/"`, as the app publishes it to iOS. */ -public struct Credential { +public struct Credential: Equatable, Hashable { public var record: String public var title: String public var user: String @@ -834,40 +883,16 @@ public struct Credential { self.user = user self.host = host } + + + + } #if compiler(>=6) extension Credential: Sendable {} #endif - -extension Credential: Equatable, Hashable { - public static func ==(lhs: Credential, rhs: Credential) -> Bool { - if lhs.record != rhs.record { - return false - } - if lhs.title != rhs.title { - return false - } - if lhs.user != rhs.user { - return false - } - if lhs.host != rhs.host { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(record) - hasher.combine(title) - hasher.combine(user) - hasher.combine(host) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -913,7 +938,7 @@ public func FfiConverterTypeCredential_lower(_ value: Credential) -> RustBuffer * `recordIdentifier` — one login can carry several passkeys, so the * credential id is what names the passkey itself. */ -public struct PasskeyAccount { +public struct PasskeyAccount: Equatable, Hashable { public var record: String public var credentialId: Data public var userName: String @@ -937,44 +962,16 @@ public struct PasskeyAccount { self.userDisplayName = userDisplayName self.createdAt = createdAt } + + + + } #if compiler(>=6) extension PasskeyAccount: Sendable {} #endif - -extension PasskeyAccount: Equatable, Hashable { - public static func ==(lhs: PasskeyAccount, rhs: PasskeyAccount) -> Bool { - if lhs.record != rhs.record { - return false - } - if lhs.credentialId != rhs.credentialId { - return false - } - if lhs.userName != rhs.userName { - return false - } - if lhs.userDisplayName != rhs.userDisplayName { - return false - } - if lhs.createdAt != rhs.createdAt { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(record) - hasher.combine(credentialId) - hasher.combine(userName) - hasher.combine(userDisplayName) - hasher.combine(createdAt) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1020,7 +1017,7 @@ public func FfiConverterTypePasskeyAccount_lower(_ value: PasskeyAccount) -> Rus * the list, `ASPasskeyCredentialRequest` for a QuickType identity), and the * account the user picked. */ -public struct PasskeyAssertion { +public struct PasskeyAssertion: Equatable, Hashable { public var rpId: String /** * The SHA-256 of the `clientDataJSON` iOS wrote. @@ -1058,40 +1055,16 @@ public struct PasskeyAssertion { self.allowedCredentialIds = allowedCredentialIds self.record = record } + + + + } #if compiler(>=6) extension PasskeyAssertion: Sendable {} #endif - -extension PasskeyAssertion: Equatable, Hashable { - public static func ==(lhs: PasskeyAssertion, rhs: PasskeyAssertion) -> Bool { - if lhs.rpId != rhs.rpId { - return false - } - if lhs.clientDataHash != rhs.clientDataHash { - return false - } - if lhs.allowedCredentialIds != rhs.allowedCredentialIds { - return false - } - if lhs.record != rhs.record { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(rpId) - hasher.combine(clientDataHash) - hasher.combine(allowedCredentialIds) - hasher.combine(record) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1133,7 +1106,7 @@ public func FfiConverterTypePasskeyAssertion_lower(_ value: PasskeyAssertion) -> /** * A registration, as iOS hands it over (`ASPasskeyCredentialRequest`). */ -public struct PasskeyRegistration { +public struct PasskeyRegistration: Equatable, Hashable { public var rpId: String public var rpName: String? public var userName: String @@ -1167,56 +1140,16 @@ public struct PasskeyRegistration { self.excludedCredentialIds = excludedCredentialIds self.supportedAlgorithms = supportedAlgorithms } + + + + } #if compiler(>=6) extension PasskeyRegistration: Sendable {} #endif - -extension PasskeyRegistration: Equatable, Hashable { - public static func ==(lhs: PasskeyRegistration, rhs: PasskeyRegistration) -> Bool { - if lhs.rpId != rhs.rpId { - return false - } - if lhs.rpName != rhs.rpName { - return false - } - if lhs.userName != rhs.userName { - return false - } - if lhs.userDisplayName != rhs.userDisplayName { - return false - } - if lhs.userHandle != rhs.userHandle { - return false - } - if lhs.clientDataHash != rhs.clientDataHash { - return false - } - if lhs.excludedCredentialIds != rhs.excludedCredentialIds { - return false - } - if lhs.supportedAlgorithms != rhs.supportedAlgorithms { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(rpId) - hasher.combine(rpName) - hasher.combine(userName) - hasher.combine(userDisplayName) - hasher.combine(userHandle) - hasher.combine(clientDataHash) - hasher.combine(excludedCredentialIds) - hasher.combine(supportedAlgorithms) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1266,7 +1199,7 @@ public func FfiConverterTypePasskeyRegistration_lower(_ value: PasskeyRegistrati /** * What a chosen login fills. */ -public struct Password { +public struct Password: Equatable, Hashable { public var user: String public var password: String @@ -1276,32 +1209,16 @@ public struct Password { self.user = user self.password = password } + + + + } #if compiler(>=6) extension Password: Sendable {} #endif - -extension Password: Equatable, Hashable { - public static func ==(lhs: Password, rhs: Password) -> Bool { - if lhs.user != rhs.user { - return false - } - if lhs.password != rhs.password { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(user) - hasher.combine(password) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1339,7 +1256,7 @@ public func FfiConverterTypePassword_lower(_ value: Password) -> RustBuffer { /** * What `ASPasskeyRegistrationCredential` carries back besides what iOS sent. */ -public struct RegisteredPasskey { +public struct RegisteredPasskey: Equatable, Hashable { public var credentialId: Data /** * CBOR, "none" attestation. @@ -1355,32 +1272,16 @@ public struct RegisteredPasskey { self.credentialId = credentialId self.attestationObject = attestationObject } + + + + } #if compiler(>=6) extension RegisteredPasskey: Sendable {} #endif - -extension RegisteredPasskey: Equatable, Hashable { - public static func ==(lhs: RegisteredPasskey, rhs: RegisteredPasskey) -> Bool { - if lhs.credentialId != rhs.credentialId { - return false - } - if lhs.attestationObject != rhs.attestationObject { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(credentialId) - hasher.combine(attestationObject) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1419,7 +1320,7 @@ public func FfiConverterTypeRegisteredPasskey_lower(_ value: RegisteredPasskey) * The active vault's place, and the keychain item its key is in. Read * without the key: what Swift needs to know before it asks for Face ID. */ -public struct VaultLocation { +public struct VaultLocation: Equatable, Hashable { /** * The data dir: `/app.rowel.mobile`, and its `dev` subdir in a * debug build, as the app lays it out (`layout::app_group_root`). @@ -1457,40 +1358,16 @@ public struct VaultLocation { self.keychainService = keychainService self.keychainAccount = keychainAccount } + + + + } #if compiler(>=6) extension VaultLocation: Sendable {} #endif - -extension VaultLocation: Equatable, Hashable { - public static func ==(lhs: VaultLocation, rhs: VaultLocation) -> Bool { - if lhs.root != rhs.root { - return false - } - if lhs.workspace != rhs.workspace { - return false - } - if lhs.keychainService != rhs.keychainService { - return false - } - if lhs.keychainAccount != rhs.keychainAccount { - return false - } - return true - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(root) - hasher.combine(workspace) - hasher.combine(keychainService) - hasher.combine(keychainAccount) - } -} - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1532,7 +1409,8 @@ public func FfiConverterTypeVaultLocation_lower(_ value: VaultLocation) -> RustB /** * Why the vault cannot be read. Each case is one thing the extension says. */ -public enum AutofillError: Swift.Error { +public +enum AutofillError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { @@ -1580,8 +1458,21 @@ public enum AutofillError: Swift.Error { case Unsupported case Io(message: String ) + + + + + + + public var errorDescription: String? { + String(reflecting: self) + } + } +#if compiler(>=6) +extension AutofillError: Sendable {} +#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -1674,21 +1565,6 @@ public func FfiConverterTypeAutofillError_lower(_ value: AutofillError) -> RustB return FfiConverterTypeAutofillError.lower(value) } - -extension AutofillError: Equatable, Hashable {} - - - - -extension AutofillError: Foundation.LocalizedError { - public var errorDescription: String? { - String(reflecting: self) - } -} - - - - #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1843,7 +1719,8 @@ fileprivate struct FfiConverterSequenceTypePasskeyAccount: FfiConverterRustBuffe */ public func appGroup() -> String { return try! FfiConverterString.lift(try! rustCall() { - uniffi_rowel_autofill_fn_func_app_group($0 + uniffiCallStatus in + uniffi_rowel_autofill_fn_func_app_group(uniffiCallStatus ) }) } @@ -1852,9 +1729,10 @@ public func appGroup() -> String { */ public func openVault(location: VaultLocation, key: Data)throws -> Vault { return try FfiConverterTypeVault_lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { + uniffiCallStatus in uniffi_rowel_autofill_fn_func_open_vault( FfiConverterTypeVaultLocation_lower(location), - FfiConverterData.lower(key),$0 + FfiConverterData.lower(key),uniffiCallStatus ) }) } @@ -1864,8 +1742,9 @@ public func openVault(location: VaultLocation, key: Data)throws -> Vault { */ public func vaultLocation(container: String)throws -> VaultLocation { return try FfiConverterTypeVaultLocation_lift(try rustCallWithError(FfiConverterTypeAutofillError_lift) { + uniffiCallStatus in uniffi_rowel_autofill_fn_func_vault_location( - FfiConverterString.lower(container),$0 + FfiConverterString.lower(container),uniffiCallStatus ) }) } @@ -1879,34 +1758,34 @@ private enum InitializationResult { // the code inside is only computed once. private let initializationResult: InitializationResult = { // Get the bindings contract version from our ComponentInterface - let bindings_contract_version = 29 + let bindings_contract_version = 30 // Get the scaffolding contract version by calling the into the dylib let scaffolding_contract_version = ffi_rowel_autofill_uniffi_contract_version() if bindings_contract_version != scaffolding_contract_version { return InitializationResult.contractVersionMismatch } - if (uniffi_rowel_autofill_checksum_func_app_group() != 42569) { + if (uniffi_rowel_autofill_checksum_func_app_group() != 14735) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_func_open_vault() != 21081) { + if (uniffi_rowel_autofill_checksum_func_open_vault() != 57544) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_func_vault_location() != 38345) { + if (uniffi_rowel_autofill_checksum_func_vault_location() != 60122) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_method_vault_assert_passkey() != 27995) { + if (uniffi_rowel_autofill_checksum_method_vault_assert_passkey() != 63665) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_method_vault_credentials_for() != 14547) { + if (uniffi_rowel_autofill_checksum_method_vault_credentials_for() != 42825) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_method_vault_passkeys_for() != 46537) { + if (uniffi_rowel_autofill_checksum_method_vault_passkeys_for() != 38598) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_method_vault_password() != 27197) { + if (uniffi_rowel_autofill_checksum_method_vault_password() != 17362) { return InitializationResult.apiChecksumMismatch } - if (uniffi_rowel_autofill_checksum_method_vault_register_passkey() != 13741) { + if (uniffi_rowel_autofill_checksum_method_vault_register_passkey() != 17262) { return InitializationResult.apiChecksumMismatch } diff --git a/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofillFFI.h b/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofillFFI.h index 86fb980f..c862fc97 100644 --- a/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofillFFI.h +++ b/src-tauri/gen/apple/Sources/autofill/generated/rowel_autofillFFI.h @@ -50,9 +50,9 @@ typedef void (*UniffiRustFutureContinuationCallback)(uint64_t, int8_t ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_FREE -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_FREE -typedef void (*UniffiForeignFutureFree)(uint64_t +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK +typedef void (*UniffiForeignFutureDroppedCallback)(uint64_t ); #endif @@ -62,228 +62,220 @@ typedef void (*UniffiCallbackInterfaceFree)(uint64_t ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE -#define UNIFFI_FFIDEF_FOREIGN_FUTURE -typedef struct UniffiForeignFuture { +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_CLONE +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_CLONE +typedef uint64_t (*UniffiCallbackInterfaceClone)(uint64_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK_STRUCT +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK_STRUCT +typedef struct UniffiForeignFutureDroppedCallbackStruct { uint64_t handle; - UniffiForeignFutureFree _Nonnull free; -} UniffiForeignFuture; + UniffiForeignFutureDroppedCallback _Nonnull free; +} UniffiForeignFutureDroppedCallbackStruct; #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U8 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U8 -typedef struct UniffiForeignFutureStructU8 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U8 +typedef struct UniffiForeignFutureResultU8 { uint8_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructU8; +} UniffiForeignFutureResultU8; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U8 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U8 -typedef void (*UniffiForeignFutureCompleteU8)(uint64_t, UniffiForeignFutureStructU8 +typedef void (*UniffiForeignFutureCompleteU8)(uint64_t, UniffiForeignFutureResultU8 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I8 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I8 -typedef struct UniffiForeignFutureStructI8 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I8 +typedef struct UniffiForeignFutureResultI8 { int8_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructI8; +} UniffiForeignFutureResultI8; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I8 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I8 -typedef void (*UniffiForeignFutureCompleteI8)(uint64_t, UniffiForeignFutureStructI8 +typedef void (*UniffiForeignFutureCompleteI8)(uint64_t, UniffiForeignFutureResultI8 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U16 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U16 -typedef struct UniffiForeignFutureStructU16 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U16 +typedef struct UniffiForeignFutureResultU16 { uint16_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructU16; +} UniffiForeignFutureResultU16; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U16 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U16 -typedef void (*UniffiForeignFutureCompleteU16)(uint64_t, UniffiForeignFutureStructU16 +typedef void (*UniffiForeignFutureCompleteU16)(uint64_t, UniffiForeignFutureResultU16 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I16 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I16 -typedef struct UniffiForeignFutureStructI16 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I16 +typedef struct UniffiForeignFutureResultI16 { int16_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructI16; +} UniffiForeignFutureResultI16; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I16 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I16 -typedef void (*UniffiForeignFutureCompleteI16)(uint64_t, UniffiForeignFutureStructI16 +typedef void (*UniffiForeignFutureCompleteI16)(uint64_t, UniffiForeignFutureResultI16 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U32 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U32 -typedef struct UniffiForeignFutureStructU32 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U32 +typedef struct UniffiForeignFutureResultU32 { uint32_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructU32; +} UniffiForeignFutureResultU32; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U32 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U32 -typedef void (*UniffiForeignFutureCompleteU32)(uint64_t, UniffiForeignFutureStructU32 +typedef void (*UniffiForeignFutureCompleteU32)(uint64_t, UniffiForeignFutureResultU32 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I32 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I32 -typedef struct UniffiForeignFutureStructI32 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I32 +typedef struct UniffiForeignFutureResultI32 { int32_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructI32; +} UniffiForeignFutureResultI32; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I32 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I32 -typedef void (*UniffiForeignFutureCompleteI32)(uint64_t, UniffiForeignFutureStructI32 +typedef void (*UniffiForeignFutureCompleteI32)(uint64_t, UniffiForeignFutureResultI32 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U64 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U64 -typedef struct UniffiForeignFutureStructU64 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U64 +typedef struct UniffiForeignFutureResultU64 { uint64_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructU64; +} UniffiForeignFutureResultU64; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U64 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U64 -typedef void (*UniffiForeignFutureCompleteU64)(uint64_t, UniffiForeignFutureStructU64 +typedef void (*UniffiForeignFutureCompleteU64)(uint64_t, UniffiForeignFutureResultU64 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I64 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I64 -typedef struct UniffiForeignFutureStructI64 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I64 +typedef struct UniffiForeignFutureResultI64 { int64_t returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructI64; +} UniffiForeignFutureResultI64; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I64 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I64 -typedef void (*UniffiForeignFutureCompleteI64)(uint64_t, UniffiForeignFutureStructI64 +typedef void (*UniffiForeignFutureCompleteI64)(uint64_t, UniffiForeignFutureResultI64 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F32 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F32 -typedef struct UniffiForeignFutureStructF32 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F32 +typedef struct UniffiForeignFutureResultF32 { float returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructF32; +} UniffiForeignFutureResultF32; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F32 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F32 -typedef void (*UniffiForeignFutureCompleteF32)(uint64_t, UniffiForeignFutureStructF32 +typedef void (*UniffiForeignFutureCompleteF32)(uint64_t, UniffiForeignFutureResultF32 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F64 -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F64 -typedef struct UniffiForeignFutureStructF64 { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F64 +typedef struct UniffiForeignFutureResultF64 { double returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructF64; +} UniffiForeignFutureResultF64; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F64 #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F64 -typedef void (*UniffiForeignFutureCompleteF64)(uint64_t, UniffiForeignFutureStructF64 - ); - -#endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_POINTER -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_POINTER -typedef struct UniffiForeignFutureStructPointer { - void*_Nonnull returnValue; - RustCallStatus callStatus; -} UniffiForeignFutureStructPointer; - -#endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_POINTER -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_POINTER -typedef void (*UniffiForeignFutureCompletePointer)(uint64_t, UniffiForeignFutureStructPointer +typedef void (*UniffiForeignFutureCompleteF64)(uint64_t, UniffiForeignFutureResultF64 ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_RUST_BUFFER -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_RUST_BUFFER -typedef struct UniffiForeignFutureStructRustBuffer { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_RUST_BUFFER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_RUST_BUFFER +typedef struct UniffiForeignFutureResultRustBuffer { RustBuffer returnValue; RustCallStatus callStatus; -} UniffiForeignFutureStructRustBuffer; +} UniffiForeignFutureResultRustBuffer; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER -typedef void (*UniffiForeignFutureCompleteRustBuffer)(uint64_t, UniffiForeignFutureStructRustBuffer +typedef void (*UniffiForeignFutureCompleteRustBuffer)(uint64_t, UniffiForeignFutureResultRustBuffer ); #endif -#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_VOID -#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_VOID -typedef struct UniffiForeignFutureStructVoid { +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_VOID +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_VOID +typedef struct UniffiForeignFutureResultVoid { RustCallStatus callStatus; -} UniffiForeignFutureStructVoid; +} UniffiForeignFutureResultVoid; #endif #ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_VOID #define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_VOID -typedef void (*UniffiForeignFutureCompleteVoid)(uint64_t, UniffiForeignFutureStructVoid +typedef void (*UniffiForeignFutureCompleteVoid)(uint64_t, UniffiForeignFutureResultVoid ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_CLONE_VAULT #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_CLONE_VAULT -void*_Nonnull uniffi_rowel_autofill_fn_clone_vault(void*_Nonnull ptr, RustCallStatus *_Nonnull out_status +uint64_t uniffi_rowel_autofill_fn_clone_vault(uint64_t handle, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_FREE_VAULT #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_FREE_VAULT -void uniffi_rowel_autofill_fn_free_vault(void*_Nonnull ptr, RustCallStatus *_Nonnull out_status +void uniffi_rowel_autofill_fn_free_vault(uint64_t handle, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_ASSERT_PASSKEY #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_ASSERT_PASSKEY -RustBuffer uniffi_rowel_autofill_fn_method_vault_assert_passkey(void*_Nonnull ptr, RustBuffer request, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_rowel_autofill_fn_method_vault_assert_passkey(uint64_t ptr, RustBuffer request, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_CREDENTIALS_FOR #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_CREDENTIALS_FOR -RustBuffer uniffi_rowel_autofill_fn_method_vault_credentials_for(void*_Nonnull ptr, RustBuffer service_identifiers, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_rowel_autofill_fn_method_vault_credentials_for(uint64_t ptr, RustBuffer service_identifiers, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_PASSKEYS_FOR #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_PASSKEYS_FOR -RustBuffer uniffi_rowel_autofill_fn_method_vault_passkeys_for(void*_Nonnull ptr, RustBuffer rp_id, RustBuffer allowed_credential_ids, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_rowel_autofill_fn_method_vault_passkeys_for(uint64_t ptr, RustBuffer rp_id, RustBuffer allowed_credential_ids, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_PASSWORD #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_PASSWORD -RustBuffer uniffi_rowel_autofill_fn_method_vault_password(void*_Nonnull ptr, RustBuffer record, RustBuffer service_identifiers, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_rowel_autofill_fn_method_vault_password(uint64_t ptr, RustBuffer record, RustBuffer service_identifiers, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_REGISTER_PASSKEY #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_METHOD_VAULT_REGISTER_PASSKEY -RustBuffer uniffi_rowel_autofill_fn_method_vault_register_passkey(void*_Nonnull ptr, RustBuffer request, RustCallStatus *_Nonnull out_status +RustBuffer uniffi_rowel_autofill_fn_method_vault_register_passkey(uint64_t ptr, RustBuffer request, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_FUNC_APP_GROUP @@ -294,7 +286,7 @@ RustBuffer uniffi_rowel_autofill_fn_func_app_group(RustCallStatus *_Nonnull out_ #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_FUNC_OPEN_VAULT #define UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_FUNC_OPEN_VAULT -void*_Nonnull uniffi_rowel_autofill_fn_func_open_vault(RustBuffer location, RustBuffer key, RustCallStatus *_Nonnull out_status +uint64_t uniffi_rowel_autofill_fn_func_open_vault(RustBuffer location, RustBuffer key, RustCallStatus *_Nonnull out_status ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_ROWEL_AUTOFILL_FN_FUNC_VAULT_LOCATION @@ -522,26 +514,6 @@ void ffi_rowel_autofill_rust_future_free_f64(uint64_t handle double ffi_rowel_autofill_rust_future_complete_f64(uint64_t handle, RustCallStatus *_Nonnull out_status ); #endif -#ifndef UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_POLL_POINTER -#define UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_POLL_POINTER -void ffi_rowel_autofill_rust_future_poll_pointer(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data -); -#endif -#ifndef UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_CANCEL_POINTER -#define UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_CANCEL_POINTER -void ffi_rowel_autofill_rust_future_cancel_pointer(uint64_t handle -); -#endif -#ifndef UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_FREE_POINTER -#define UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_FREE_POINTER -void ffi_rowel_autofill_rust_future_free_pointer(uint64_t handle -); -#endif -#ifndef UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_COMPLETE_POINTER -#define UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_COMPLETE_POINTER -void*_Nonnull ffi_rowel_autofill_rust_future_complete_pointer(uint64_t handle, RustCallStatus *_Nonnull out_status -); -#endif #ifndef UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_POLL_RUST_BUFFER #define UNIFFI_FFIDEF_FFI_ROWEL_AUTOFILL_RUST_FUTURE_POLL_RUST_BUFFER void ffi_rowel_autofill_rust_future_poll_rust_buffer(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data From 5e319bf18e9ee011b86b973ea99ffeaf3358b7d4 Mon Sep 17 00:00:00 2001 From: Alex Chaplinsky Date: Sun, 11 Oct 2026 01:17:17 +0700 Subject: [PATCH 7/9] Revert "chore(deps): bump libc from 0.2.189 to 0.2.190 in /src-tauri" This reverts commit 856b55f64f020dd26ef514a9a083754dcb065741. --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2a95e5d8..bb312d71 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3145,9 +3145,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.190" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libdbus-sys" From 8cacf64fb894cdc4a9d6cadc3727bd31d170f422 Mon Sep 17 00:00:00 2001 From: Alex Chaplinsky Date: Sun, 11 Oct 2026 01:18:25 +0700 Subject: [PATCH 8/9] ci(deps): skip libc 0.2.190, which breaks the iOS build libc 0.2.190 gates mach_task_self() to macOS; num_threads 0.1.7 (via time -> tauri) still calls it on iOS, so iOS clippy failed. The bump is reverted in the previous commit. --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 11d4118a..398c3164 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -87,6 +87,11 @@ updates: # bump leaves two rand generations and breaks every RNG handoff. - dependency-name: rand versions: ['>=0.9'] + # libc 0.2.190 gates mach_task_self() to macOS, but num_threads 0.1.7 + # (via time -> tauri) still calls it on iOS, so the iOS build fails. + # Drop once a later libc or num_threads release builds for iOS again. + - dependency-name: libc + versions: ['0.2.190'] # Browser extension — extension/package.json + package-lock.json. A fork of # KeePassXC-Browser with dev-only tooling, so one monthly PR is enough. From ddb07e52765c50ff6c64c37f2034d8fbcb6afc6c Mon Sep 17 00:00:00 2001 From: Alex Chaplinsky Date: Sun, 11 Oct 2026 01:20:33 +0700 Subject: [PATCH 9/9] ci: the bindings check also fails on untracked generated files git diff misses a deleted file that bindgen.sh recreates untracked; use git status --porcelain instead. --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1c77ec3..c09add92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -228,8 +228,14 @@ jobs: run: | set -euo pipefail sh src-tauri/crates/autofill/bindgen.sh - git diff --exit-code -- src-tauri/gen/apple/Sources/autofill/generated \ - || { echo '::error::Stale UniFFI bindings: run src-tauri/crates/autofill/bindgen.sh and commit what it writes'; exit 1; } + # status, not diff: a deleted file comes back untracked, which diff misses. + generated=src-tauri/gen/apple/Sources/autofill/generated + if [ -n "$(git status --porcelain -- "$generated")" ]; then + git status --short -- "$generated" + git diff -- "$generated" + echo '::error::Stale UniFFI bindings: run src-tauri/crates/autofill/bindgen.sh and commit what it writes' + exit 1 + fi # Malformed XML in any of these only surfaces at build or upload time # otherwise, and a dropped privacy manifest is not an error at all — App