Skip to content

Android / Linux Support - #150

Merged
codefiesta merged 14 commits into
mainfrom
android
Aug 20, 2026
Merged

Android / Linux Support#150
codefiesta merged 14 commits into
mainfrom
android

Conversation

@codefiesta

@codefiesta codefiesta commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Description

This change provides Android and Linux Support. In places where we won't be able to import Security, Network, or SwiftUI modules so we've wrapped these imports in macros with libs provided by the Core Libs Foundation as well as any code specific paths.

Changes include the following:

  • Wrapping Apple specified imports in canImport(Security) macro checks.
  • Abstracted out the Keychain storage into a protocol that allows for os specific implementations of their preferred way of secure storage.
  • Calls into Keychain.Storage write methods are wrapped with Locks inside the Keychain.
extension Keychain {

    // Provides the storage protocols used for storing sensitive data.
    // The storage operations should all be wrapped in a locking
    // mechanism to prevent any potential data races.
    protocol Storage {

        /// The owning account identifier.
        /// - Parameter account: a key indicating the account owner. Ideally, use the application identifier for this value.
        init(account: String)

        /// The account owner of this keychain storage.
        var account: String { get }

        /// Returns a list of keys owned by this account.
        var keys: [String] { get }

        /// Sets the data for the specified key
        /// - Parameters:
        ///   - data: the data to store for the specified key
        ///   - key: the key to use for the data
        /// - Returns: true if able to set the data, otherwise false
        func set(_ data: Data, for key: String) throws -> Bool

        /// Fetches storeed data from the data store with the specified key.
        /// - Parameter key: the keychain key
        /// - Returns: the data for the specified key or nil if not found
        func get(key: String) throws -> Data?

        /// Deletes the value for the specified key.
        /// - Parameter key: the key to delete
        /// - Returns: true if able to delete from the storage, otherwise false
        func delete(key: String) -> Bool

        /// Clears all values and keys for the current account.
        /// - Returns: true if values were cleared, otherwise false.
        func clear() -> Bool

        /// Builds the combined account key by prefixing the specified key with the account.
        /// - Parameter key: the key to prefix.
        /// - Returns: the unique account key to use
        func accountKey(_ key: String) -> String
    }
}
/// A helper class used to interact with Keychain storage access. Wraps all storage write operations with threadsafe locks.
class Keychain: @unchecked Sendable {

    /// Initializes the keychain with an overridden accound identifier.
    /// - Parameter account: a key indicating the account owner. Ideally, use the application identifier for this value.
    public init(_ account: String) {
        assert(account.isNotEmpty, "❌ The account identifier cannot be empty.")
        #if canImport(Security)
        self.storage = DefaultStorage(account: account)
        #elseif os(Android)
        // TODO: Android storage not implemented
        #elseif os(Linux)
        // TODO: Linux storage not implemented
        #endif
    }
}

Fixes #149

Note: We'll need to follow up with implementations for Android and Linux storage.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@codefiesta codefiesta self-assigned this Aug 17, 2026
@codefiesta codefiesta added android Android related issue. linux Linux related labels Aug 20, 2026
@codefiesta
codefiesta marked this pull request as ready for review August 20, 2026 16:39
@codefiesta
codefiesta merged commit 03a594b into main Aug 20, 2026
1 check passed
@codefiesta
codefiesta deleted the android branch August 20, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

android Android related issue. linux Linux related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android / Linux Support

1 participant